001package org.tynamo.resteasy; 002 003 004import java.util.Collection; 005 006import javax.ws.rs.ext.Provider; 007 008import org.apache.tapestry5.internal.InternalConstants; 009import org.apache.tapestry5.ioc.Configuration; 010import org.apache.tapestry5.ioc.MappedConfiguration; 011import org.apache.tapestry5.ioc.ObjectLocator; 012import org.apache.tapestry5.ioc.OrderedConfiguration; 013import org.apache.tapestry5.ioc.ServiceBinder; 014import org.apache.tapestry5.ioc.annotations.Contribute; 015import org.apache.tapestry5.ioc.annotations.InjectService; 016import org.apache.tapestry5.ioc.annotations.Symbol; 017import org.apache.tapestry5.ioc.services.ClassNameLocator; 018import org.apache.tapestry5.ioc.services.FactoryDefaults; 019import org.apache.tapestry5.ioc.services.SymbolProvider; 020import org.apache.tapestry5.services.HttpServletRequestFilter; 021import org.apache.tapestry5.services.HttpServletRequestHandler; 022import org.jboss.resteasy.util.GetRestful; 023import org.slf4j.Logger; 024 025/** 026 * This module is automatically included as part of the Tapestry IoC Registry 027 */ 028public class ResteasyModule 029{ 030 031 public static void bind(ServiceBinder binder) 032 { 033 // Make bind() calls on the binder object to define most IoC services. 034 // Use service builder methods (example below) when the implementation 035 // is provided inline, or requires more initialization than simply 036 // invoking the constructor. 037 binder.bind(javax.ws.rs.core.Application.class, org.tynamo.resteasy.Application.class); 038 binder.bind(HttpServletRequestFilter.class, ResteasyRequestFilter.class).withId("ResteasyRequestFilter"); 039 binder.bind(HttpServletRequestFilter.class, JSAPIRequestFilter.class).withId("JSAPIRequestFilter"); 040 } 041 042 @Contribute(HttpServletRequestHandler.class) 043 public static void httpServletRequestHandler(OrderedConfiguration<HttpServletRequestFilter> configuration, 044 @InjectService("ResteasyRequestFilter") HttpServletRequestFilter resteasyRequestFilter, 045 @InjectService("JSAPIRequestFilter") HttpServletRequestFilter jsapiRequestFilter) 046 { 047 configuration.add("ResteasyRequestFilter", resteasyRequestFilter, "after:IgnoredPaths", "before:GZIP"); 048 configuration.add("JSAPIRequestFilter", jsapiRequestFilter, "after:ResteasyRequestFilter"); 049 } 050 051 @Contribute(SymbolProvider.class) 052 @FactoryDefaults 053 public static void setupSymbols(MappedConfiguration<String, Object> configuration) 054 { 055 configuration.add(ResteasySymbols.MAPPING_PREFIX, "/rest"); 056 configuration.add(ResteasySymbols.MAPPING_PREFIX_JSAPI, "/jsapi"); 057 configuration.add(ResteasySymbols.AUTOSCAN_REST_PACKAGE, true); 058 configuration.add(ResteasySymbols.CORS_ENABLED, false); 059 } 060 061 @Contribute(javax.ws.rs.core.Application.class) 062 public static void javaxWsRsCoreApplication(Configuration<Object> singletons, 063 ObjectLocator locator, 064 ResteasyPackageManager resteasyPackageManager, 065 ClassNameLocator classNameLocator, 066 Logger logger) 067 { 068 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 069 070 for (String packageName : resteasyPackageManager.getPackageNames()) 071 { 072 for (String className : classNameLocator.locateClassNames(packageName)) 073 { 074 try 075 { 076 Class clazz = contextClassLoader.loadClass(className); 077 Class rootResourceClass = GetRestful.getRootResourceClass(clazz); 078 079 if (rootResourceClass != null) 080 { 081 if (rootResourceClass.equals(clazz)) 082 { 083 if (!clazz.isInterface()) 084 { 085 singletons.add(locator.autobuild(clazz)); 086 } 087 } else 088 { 089 try 090 { 091 singletons.add(locator.getService(rootResourceClass)); 092 } catch (RuntimeException e) 093 { 094 logger.info(e.getMessage()); 095 logger.info("Trying to create a proxy for " + rootResourceClass.getName()); 096 singletons.add(locator.proxy(rootResourceClass, clazz)); 097 } 098 } 099 } else if (clazz.isAnnotationPresent(Provider.class)) 100 { 101 singletons.add(locator.autobuild(clazz)); 102 } 103 104 } catch (ClassNotFoundException ex) 105 { 106 throw new RuntimeException(ex); 107 } 108 } 109 } 110 } 111 112 // Contributes the package "<root>.rest" (InternalConstants.TAPESTRY_APP_PACKAGE_PARAM + ".rest") 113 // to the configuration, so that it will be scanned for annotated REST resource classes. 114 @Contribute(ResteasyPackageManager.class) 115 public static void resteasyPackageManager(Configuration<String> configuration, 116 @Symbol(InternalConstants.TAPESTRY_APP_PACKAGE_PARAM) String appRootPackage, 117 @Symbol(ResteasySymbols.AUTOSCAN_REST_PACKAGE) Boolean shouldScanRestPackage) 118 { 119 if (shouldScanRestPackage) 120 { 121 configuration.add(appRootPackage + ".rest"); 122 } 123 } 124 125 public static ResteasyPackageManager buildResteasyPackageManager(final Collection<String> packageNames) 126 { 127 return new ResteasyPackageManager() 128 { 129 public Collection<String> getPackageNames() 130 { 131 return packageNames; 132 } 133 }; 134 } 135}