org.everrest.spring.SpringComponentsLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.everrest.spring.SpringComponentsLoader.java

Source

/*******************************************************************************
 * Copyright (c) 2012-2014 Codenvy, S.A.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Codenvy, S.A. - initial API and implementation
 *******************************************************************************/
package org.everrest.spring;

import org.everrest.core.ApplicationContext;
import org.everrest.core.DependencySupplier;
import org.everrest.core.Filter;
import org.everrest.core.FilterDescriptor;
import org.everrest.core.InitialProperties;
import org.everrest.core.ResourceBinder;
import org.everrest.core.impl.ApplicationContextImpl;
import org.everrest.core.impl.ApplicationProviderBinder;
import org.everrest.core.impl.EverrestApplication;
import org.everrest.core.impl.EverrestConfiguration;
import org.everrest.core.impl.EverrestProcessor;
import org.everrest.core.impl.FileCollectorDestroyer;
import org.everrest.core.impl.FilterDescriptorImpl;
import org.everrest.core.impl.async.AsynchronousJobPool;
import org.everrest.core.impl.async.AsynchronousJobService;
import org.everrest.core.impl.async.AsynchronousProcessListWriter;
import org.everrest.core.impl.method.filter.SecurityConstraint;
import org.everrest.core.impl.provider.ProviderDescriptorImpl;
import org.everrest.core.impl.resource.AbstractResourceDescriptorImpl;
import org.everrest.core.impl.resource.ResourceDescriptorValidator;
import org.everrest.core.provider.ProviderDescriptor;
import org.everrest.core.resource.AbstractResourceDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Provider;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * This loader registers any bean annotated with @Path, @Provider or @Filter in the EverRest framework.
 *
 * @author andrew00x
 */
public class SpringComponentsLoader implements BeanFactoryPostProcessor, HandlerMapping {
    private static abstract class _Lifecycle implements org.springframework.context.Lifecycle {
        private final AtomicBoolean flag = new AtomicBoolean(false);

        @Override
        public final void start() {
            doStart();
            flag.set(true);
        }

        @Override
        public final void stop() {
            doStop();
            flag.set(false);
        }

        @Override
        public final boolean isRunning() {
            return flag.get();
        }

        void doStart() {
        }

        void doStop() {
        }
    }

    private static final class SpringEverrestProcessorLifecycle extends _Lifecycle {
        private final EverrestProcessor processor;

        private SpringEverrestProcessorLifecycle(EverrestProcessor processor) {
            this.processor = processor;
        }

        @Override
        void doStart() {
            processor.start();
        }

        @Override
        void doStop() {
            processor.stop();
        }
    }

    private static final class SpringFileCollectorDestroyer extends _Lifecycle {
        private final FileCollectorDestroyer fileCollectorDestroyer;

        public SpringFileCollectorDestroyer(FileCollectorDestroyer fileCollectorDestroyer) {
            this.fileCollectorDestroyer = fileCollectorDestroyer;
        }

        @Override
        void doStop() {
            fileCollectorDestroyer.stopFileCollector();
        }
    }

    protected ResourceBinder resources;
    protected ApplicationProviderBinder providers;
    protected EverrestProcessor processor;
    protected EverrestConfiguration configuration;

    public SpringComponentsLoader(ResourceBinder resources, ApplicationProviderBinder providers,
            DependencySupplier dependencies) {
        this(resources, providers, new EverrestConfiguration(), dependencies);
    }

    public SpringComponentsLoader(ResourceBinder resources, ApplicationProviderBinder providers,
            EverrestConfiguration configuration, DependencySupplier dependencies) {
        this.resources = resources;
        this.providers = providers;
        this.configuration = configuration;
        this.processor = new EverrestProcessor(resources, providers, dependencies, configuration, null);
    }

    protected SpringComponentsLoader() {
    }

    @Override
    public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        return new HandlerExecutionChain(processor);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.registerSingleton("org.everrest.lifecycle.SpringEverrestProcessorLifecycle",
                new SpringEverrestProcessorLifecycle(processor));
        beanFactory.registerSingleton("org.everrest.lifecycle.SpringFileCollectorDestroyer",
                new SpringFileCollectorDestroyer(makeFileCollectorDestroyer()));
        EverrestApplication everrest = makeEverrestApplication();

        ResourceDescriptorValidator rdv = ResourceDescriptorValidator.getInstance();
        addAutowiredDependencies(beanFactory);
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
            Class<?> beanClass = beanFactory.getType(beanName);
            if (beanClass.getAnnotation(Provider.class) != null) {
                ProviderDescriptor pDescriptor = new ProviderDescriptorImpl(beanClass);
                pDescriptor.accept(rdv);
                everrest.addFactory(new SpringObjectFactory<>(pDescriptor, beanName, beanFactory));
            } else if (beanClass.getAnnotation(Filter.class) != null) {
                FilterDescriptor fDescriptor = new FilterDescriptorImpl(beanClass);
                fDescriptor.accept(rdv);
                everrest.addFactory(new SpringObjectFactory<>(fDescriptor, beanName, beanFactory));
            } else if (beanClass.getAnnotation(Path.class) != null) {
                AbstractResourceDescriptor rDescriptor = new AbstractResourceDescriptorImpl(beanClass);
                rDescriptor.accept(rdv);
                everrest.addFactory(new SpringObjectFactory<>(rDescriptor, beanName, beanFactory));
            }
        }

        processor.addApplication(everrest);
    }

    protected FileCollectorDestroyer makeFileCollectorDestroyer() {
        return new FileCollectorDestroyer();
    }

    protected EverrestApplication makeEverrestApplication() {
        final EverrestApplication everrest = new EverrestApplication();
        if (configuration.isAsynchronousSupported()) {
            everrest.addResource(configuration.getAsynchronousServicePath(), AsynchronousJobService.class);
            everrest.addSingleton(new AsynchronousJobPool(configuration));
            everrest.addSingleton(new AsynchronousProcessListWriter());
        }
        if (configuration.isCheckSecurity()) {
            everrest.addSingleton(new SecurityConstraint());
        }
        return everrest;
    }

    /**
     * Add binding for HttpHeaders, InitialProperties, Request, SecurityContext, UriInfo. All this types will be
     * supported for injection in constructor or fields of component of Spring IoC container.
     *
     * @param beanFactory
     *         bean factory
     * @see org.springframework.beans.factory.annotation.Autowired
     */
    protected void addAutowiredDependencies(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.registerResolvableDependency(HttpHeaders.class, new ObjectFactory<HttpHeaders>() {
            @Override
            public HttpHeaders getObject() {
                ApplicationContext context = ApplicationContextImpl.getCurrent();
                if (context == null) {
                    throw new IllegalStateException("EverRest ApplicationContext is not initialized.");
                }
                return context.getHttpHeaders();
            }
        });
        beanFactory.registerResolvableDependency(InitialProperties.class, new ObjectFactory<InitialProperties>() {
            @Override
            public InitialProperties getObject() {
                ApplicationContext context = ApplicationContextImpl.getCurrent();
                if (context == null) {
                    throw new IllegalStateException("EverRest ApplicationContext is not initialized.");
                }
                return context.getInitialProperties();
            }
        });
        beanFactory.registerResolvableDependency(Request.class, new ObjectFactory<Request>() {
            @Override
            public Request getObject() {
                ApplicationContext context = ApplicationContextImpl.getCurrent();
                if (context == null) {
                    throw new IllegalStateException("EverRest ApplicationContext is not initialized.");
                }
                return context.getRequest();
            }
        });
        beanFactory.registerResolvableDependency(SecurityContext.class, new ObjectFactory<SecurityContext>() {
            @Override
            public SecurityContext getObject() {
                ApplicationContext context = ApplicationContextImpl.getCurrent();
                if (context == null) {
                    throw new IllegalStateException("EverRest ApplicationContext is not initialized.");
                }
                return context.getSecurityContext();
            }
        });
        beanFactory.registerResolvableDependency(UriInfo.class, new ObjectFactory<UriInfo>() {
            @Override
            public UriInfo getObject() {
                ApplicationContext context = ApplicationContextImpl.getCurrent();
                if (context == null) {
                    throw new IllegalStateException("EverRest ApplicationContext is not initialized.");
                }
                return context.getUriInfo();
            }
        });
        beanFactory.registerResolvableDependency(javax.ws.rs.core.Application.class,
                new ObjectFactory<javax.ws.rs.core.Application>() {
                    @Override
                    public javax.ws.rs.core.Application getObject() {
                        ApplicationContext context = ApplicationContextImpl.getCurrent();
                        if (context == null) {
                            throw new IllegalStateException("EverRest ApplicationContext is not initialized.");
                        }
                        return context.getApplication();
                    }
                });
    }

    protected ResourceBinder getResources() {
        return resources;
    }

    protected ApplicationProviderBinder getProviders() {
        return providers;
    }

    protected EverrestProcessor getProcessor() {
        return processor;
    }
}