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 "&lt;root&gt;.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}