001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.rest.springboot; 014 015import org.apache.juneau.rest.*; 016import org.apache.juneau.rest.springboot.annotation.*; 017import org.springframework.beans.BeansException; 018import org.springframework.beans.factory.config.*; 019import org.springframework.beans.factory.support.BeanDefinitionRegistry; 020import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; 021import org.springframework.beans.factory.support.RootBeanDefinition; 022import org.springframework.boot.web.servlet.ServletRegistrationBean; 023import org.springframework.context.*; 024import org.springframework.core.type.*; 025 026import java.util.*; 027 028import javax.servlet.Servlet; 029 030/** 031 * Processes the {@link JuneauRestRoot} annotation on the Spring application class and <ja>@Bean</ja> methods. 032 */ 033public class JuneauRestPostProcessor implements BeanDefinitionRegistryPostProcessor { 034 035 private final Class<?> appClass; 036 private final RestResourceResolver restResourceResolver; 037 private BeanDefinitionRegistry registry; 038 039 /** 040 * Constructor. 041 * 042 * @param ctx The spring application context. 043 * @param appClass The spring application class. Can be <jk>null</jk>. 044 */ 045 public JuneauRestPostProcessor(ConfigurableApplicationContext ctx, Class<?> appClass) { 046 this.appClass = appClass; 047 this.restResourceResolver = new SpringRestResourceResolver(ctx); 048 } 049 050 @Override /* BeanDefinitionRegistryPostProcessor */ 051 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { 052 this.registry = registry; 053 } 054 055 @Override /* BeanDefinitionRegistryPostProcessor */ 056 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 057 try { 058 Map<String,RestServlet> m = new LinkedHashMap<>(); 059 060 // @JuneauRestRoot on App class. 061 if (appClass != null) { 062 JuneauRestRoot a = appClass.getAnnotation(JuneauRestRoot.class); 063 if (a != null) 064 for (Class<? extends RestServlet> c : a.servlets()) 065 m.put(c.getName(), c.newInstance()); 066 } 067 068 // @JuneauRestRoot on classes. 069 for (Map.Entry<String,Object> e : beanFactory.getBeansWithAnnotation(JuneauRestRoot.class).entrySet()) 070 if (e.getValue() instanceof RestServlet) 071 m.put(e.getKey(), (RestServlet) e.getValue()); 072 073 // @JuneauRestRoot on @Bean method. 074 for (String beanName : beanFactory.getBeanNamesForType(RestServlet.class)) { 075 BeanDefinition bd = beanFactory.getBeanDefinition(beanName); 076 if (bd.getSource() instanceof AnnotatedTypeMetadata) { 077 AnnotatedTypeMetadata metadata = (AnnotatedTypeMetadata) bd.getSource(); 078 if (metadata.isAnnotated(JuneauRestRoot.class.getName())) 079 m.put(beanName, (RestServlet) beanFactory.getBean(beanName)); 080 } 081 } 082 083 for (RestServlet rs : m.values()) { 084 rs.setRestResourceResolver(restResourceResolver); 085 ServletRegistrationBean<Servlet> reg = new ServletRegistrationBean<>(rs, '/' + rs.getPath()); 086 registry.registerBeanDefinition(reg.getServletName(), new RootBeanDefinition(ServletRegistrationBean.class, () -> reg)); 087 } 088 089 } catch (Exception e) { 090 throw new RuntimeException(e); 091 } 092 } 093}