org.libreplan.web.common.entrypoints.RedirectorSynthetiser.java Source code

Java tutorial

Introduction

Here is the source code for org.libreplan.web.common.entrypoints.RedirectorSynthetiser.java

Source

/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 2009-2010 Fundacin para o Fomento da Calidade Industrial e
 *                         Desenvolvemento Tecnolxico de Galicia
 * Copyright (C) 2010-2011 Igalia, S.L.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.libreplan.web.common.entrypoints;

import static org.libreplan.web.I18nHelper._;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.ClassUtils;

/**
 * Creates implementations of controllers that sends http redirects to the proper page <br />
 *
 * @author scar Gonzlez Fernndez <ogonzalez@igalia.com>
 */
public class RedirectorSynthetiser implements BeanFactoryPostProcessor {

    private static final Log LOG = LogFactory.getLog(RedirectorSynthetiser.class);

    private static final class SynthetizedImplementation implements InvocationHandler {

        private final ConfigurableListableBeanFactory beanFactory;

        private final Class<?> pageInterface;

        private EntryPointsHandler<?> urlHandler;

        private SynthetizedImplementation(ConfigurableListableBeanFactory beanFactory, Class<?> pageInterface) {

            this.beanFactory = beanFactory;
            this.pageInterface = pageInterface;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            EntryPointsHandler<?> redirector = getHandler();
            redirector.doTransition(method.getName(), args);

            return null;
        }

        private EntryPointsHandler<?> getHandler() {
            if (urlHandler != null) {
                return urlHandler;
            }

            URLHandlerRegistry registry = BeanFactoryUtils.beanOfType(beanFactory, URLHandlerRegistry.class);
            urlHandler = registry.getRedirectorFor(pageInterface);

            return urlHandler;
        }
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        long elapsedTime = System.currentTimeMillis();

        for (Class<?> pageInterface : findInterfacesMarkedEntryPoints()) {

            beanFactory.registerSingleton(getBeanName(pageInterface),
                    createRedirectorImplementationFor(beanFactory, pageInterface));
        }
        elapsedTime = System.currentTimeMillis() - elapsedTime;

        LOG.debug("Took " + elapsedTime + " ms to search for interfaces annotated with "
                + EntryPoints.class.getSimpleName());
    }

    private List<Class<?>> findInterfacesMarkedEntryPoints() {
        List<Class<?>> result = new ArrayList<>();
        PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourceResolver);

        for (Resource resource : findResourcesCouldMatch(resourceResolver)) {
            addIfSuitable(result, metadataReaderFactory, resource);
        }
        return result;
    }

    private Resource[] findResourcesCouldMatch(PathMatchingResourcePatternResolver resourceResolver) {
        try {
            return resourceResolver.getResources("classpath*:"
                    + ClassUtils.convertClassNameToResourcePath("org.libreplan.web") + "/" + "**/*.class");

        } catch (IOException e) {
            throw new RuntimeException(_("Could not load any resource"), e);
        }
    }

    private void addIfSuitable(List<Class<?>> accumulatedResult, CachingMetadataReaderFactory metadataReaderFactory,
            Resource resource) {
        try {
            if (resource.isReadable()) {
                MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
                AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                ClassMetadata classMetadata = metadataReader.getClassMetadata();

                if (classMetadata.isInterface()
                        && annotationMetadata.getAnnotationTypes().contains(EntryPoints.class.getName())) {

                    Class<?> klass = Class.forName(classMetadata.getClassName());
                    if (klass.isInterface()) {
                        accumulatedResult.add(klass);
                    }
                }
            }
        } catch (Exception e) {
            LOG.warn("exception processing " + resource, e);
        }
    }

    private Object createRedirectorImplementationFor(final ConfigurableListableBeanFactory beanFactory,
            final Class<?> pageInterface) {

        return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { pageInterface },
                new SynthetizedImplementation(beanFactory, pageInterface));
    }

    private static String getBeanName(Class<?> pageInterface) {
        EntryPoints annotation = pageInterface.getAnnotation(EntryPoints.class);

        return annotation.registerAs();
    }
}