blob: 34c45c75fc70ffcc382e5a1bb6bba7c0924189fb [file] [log] [blame]
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
// * with the License. You may obtain a copy of the License at *
// * *
// * http://www.apache.org/licenses/LICENSE-2.0 *
// * *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
// * specific language governing permissions and limitations under the License. *
// ***************************************************************************************************************************
package org.apache.juneau.rest.springboot;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.springboot.annotation.*;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.*;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.*;
import org.springframework.core.type.*;
import java.util.*;
import javax.servlet.Servlet;
/**
* Processes the {@link JuneauRestRoot} annotation on the Spring application class and <ja>@Bean</ja> methods.
*/
public class JuneauRestPostProcessor implements BeanDefinitionRegistryPostProcessor {
private final Class<?> appClass;
private final RestResourceResolver restResourceResolver;
private BeanDefinitionRegistry registry;
/**
* Constructor.
*
* @param ctx The spring application context.
* @param appClass The spring application class. Can be <jk>null</jk>.
*/
public JuneauRestPostProcessor(ConfigurableApplicationContext ctx, Class<?> appClass) {
this.appClass = appClass;
this.restResourceResolver = new SpringRestResourceResolver(ctx);
}
@Override /* BeanDefinitionRegistryPostProcessor */
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
this.registry = registry;
}
@Override /* BeanDefinitionRegistryPostProcessor */
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Map<String,RestServlet> m = new LinkedHashMap<>();
// @JuneauRestRoot on App class.
if (appClass != null) {
JuneauRestRoot a = appClass.getAnnotation(JuneauRestRoot.class);
if (a != null)
for (Class<? extends RestServlet> c : a.servlets())
m.put(c.getName(), c.newInstance());
}
// @JuneauRestRoot on classes.
for (Map.Entry<String,Object> e : beanFactory.getBeansWithAnnotation(JuneauRestRoot.class).entrySet())
if (e.getValue() instanceof RestServlet)
m.put(e.getKey(), (RestServlet) e.getValue());
// @JuneauRestRoot on @Bean method.
for (String beanName : beanFactory.getBeanNamesForType(RestServlet.class)) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
if (bd.getSource() instanceof AnnotatedTypeMetadata) {
AnnotatedTypeMetadata metadata = (AnnotatedTypeMetadata) bd.getSource();
if (metadata.isAnnotated(JuneauRestRoot.class.getName()))
m.put(beanName, (RestServlet) beanFactory.getBean(beanName));
}
}
for (RestServlet rs : m.values()) {
rs.setRestResourceResolver(restResourceResolver);
ServletRegistrationBean<Servlet> reg = new ServletRegistrationBean<>(rs, '/' + rs.getPath());
registry.registerBeanDefinition(reg.getServletName(), new RootBeanDefinition(ServletRegistrationBean.class, () -> reg));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}