org.spring.guice.annotation.GuiceModuleRegistrar.java Source code

Java tutorial

Introduction

Here is the source code for org.spring.guice.annotation.GuiceModuleRegistrar.java

Source

/*
 * Copyright 2012-2013 the original author or authors.
 *
 * Licensed 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.spring.guice.annotation;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.*;
import org.spring.guice.module.GuiceModuleMetadata;
import org.springframework.util.Assert;

import java.lang.annotation.Annotation;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author Dave Syer
 *
 */
public class GuiceModuleRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {

    private ResourceLoader resourceLoader = new DefaultResourceLoader();

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotation, BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder
                .genericBeanDefinition(GuiceModuleMetadataFactory.class);
        builder.addPropertyValue("includeFilters", parseFilters(annotation, "includeFilters"));
        builder.addPropertyValue("excludeFilters", parseFilters(annotation, "excludeFilters"));
        builder.addPropertyValue("includePatterns", parsePatterns(annotation, "includePatterns"));
        builder.addPropertyValue("excludePatterns", parsePatterns(annotation, "excludePatterns"));
        builder.addPropertyValue("includeNames", parseNames(annotation, "includeNames"));
        builder.addPropertyValue("excludeNames", parseNames(annotation, "excludeNames"));
        AbstractBeanDefinition definition = builder.getBeanDefinition();
        String name = new DefaultBeanNameGenerator().generateBeanName(definition, registry);
        registry.registerBeanDefinition(name, definition);
    }

    public static class GuiceModuleMetadataFactory implements FactoryBean<GuiceModuleMetadata> {

        private Collection<? extends TypeFilter> includeFilters;

        private Collection<? extends TypeFilter> excludeFilters;

        private Collection<Pattern> includePatterns;

        private Collection<Pattern> excludePatterns;

        private Collection<String> includeNames;

        private Collection<String> excludeNames;

        public void setIncludeFilters(Collection<? extends TypeFilter> includeFilters) {
            this.includeFilters = includeFilters;
        }

        public void setExcludeFilters(Collection<? extends TypeFilter> excludeFilters) {
            this.excludeFilters = excludeFilters;
        }

        public void setIncludePatterns(Collection<Pattern> includePatterns) {
            this.includePatterns = includePatterns;
        }

        public void setExcludePatterns(Collection<Pattern> excludePatterns) {
            this.excludePatterns = excludePatterns;
        }

        public void setIncludeNames(Collection<String> includeNames) {
            this.includeNames = includeNames;
        }

        public void setExcludeNames(Collection<String> excludeNames) {
            this.excludeNames = excludeNames;
        }

        @Override
        public GuiceModuleMetadata getObject() throws Exception {
            return new GuiceModuleMetadata().include(includeFilters.toArray(new TypeFilter[includeFilters.size()]))
                    .exclude(excludeFilters.toArray(new TypeFilter[excludeFilters.size()]))
                    .include(includePatterns.toArray(new Pattern[includePatterns.size()]))
                    .exclude(excludePatterns.toArray(new Pattern[excludePatterns.size()]))
                    .include(includeNames.toArray(new String[includeNames.size()]))
                    .exclude(excludeNames.toArray(new Pattern[excludeNames.size()]));
        }

        @Override
        public Class<?> getObjectType() {
            return GuiceModuleMetadata.class;
        }

        @Override
        public boolean isSingleton() {
            return false;
        }

    }

    private Set<Pattern> parsePatterns(AnnotationMetadata annotation, String attributeName) {
        Set<Pattern> result = new HashSet<Pattern>();
        AnnotationAttributes attributes = new AnnotationAttributes(
                annotation.getAnnotationAttributes(GuiceModule.class.getName()));
        String[] filters = attributes.getStringArray(attributeName);

        for (String filter : filters) {
            result.add(Pattern.compile(filter));
        }

        return result;
    }

    private Set<String> parseNames(AnnotationMetadata annotation, String attributeName) {
        Set<String> result = new HashSet<String>();
        AnnotationAttributes attributes = new AnnotationAttributes(
                annotation.getAnnotationAttributes(GuiceModule.class.getName()));
        String[] filters = attributes.getStringArray(attributeName);

        for (String filter : filters) {
            result.add(filter);
        }

        return result;
    }

    private Set<TypeFilter> parseFilters(AnnotationMetadata annotation, String attributeName) {

        Set<TypeFilter> result = new HashSet<TypeFilter>();
        AnnotationAttributes attributes = new AnnotationAttributes(
                annotation.getAnnotationAttributes(GuiceModule.class.getName()));
        AnnotationAttributes[] filters = attributes.getAnnotationArray(attributeName);

        for (AnnotationAttributes filter : filters) {
            result.addAll(typeFiltersFor(filter));
        }

        return result;
    }

    private List<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {

        List<TypeFilter> typeFilters = new ArrayList<TypeFilter>();
        FilterType filterType = filterAttributes.getEnum("type");

        for (Class<?> filterClass : filterAttributes.getClassArray("value")) {
            switch (filterType) {
            case ANNOTATION:
                Assert.isAssignable(Annotation.class, filterClass,
                        "An error occured when processing a @ComponentScan " + "ANNOTATION type filter: ");
                @SuppressWarnings("unchecked")
                Class<Annotation> annoClass = (Class<Annotation>) filterClass;
                typeFilters.add(new AnnotationTypeFilter(annoClass));
                break;
            case ASSIGNABLE_TYPE:
                typeFilters.add(new AssignableTypeFilter(filterClass));
                break;
            case CUSTOM:
                Assert.isAssignable(TypeFilter.class, filterClass,
                        "An error occured when processing a @ComponentScan " + "CUSTOM type filter: ");
                typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class));
                break;
            default:
                throw new IllegalArgumentException("Unknown filter type " + filterType);
            }
        }

        for (String expression : getPatterns(filterAttributes)) {

            String rawName = filterType.toString();

            if ("REGEX".equals(rawName)) {
                typeFilters.add(new RegexPatternTypeFilter(Pattern.compile(expression)));
            } else if ("ASPECTJ".equals(rawName)) {
                typeFilters.add(new AspectJTypeFilter(expression, this.resourceLoader.getClassLoader()));
            } else {
                throw new IllegalArgumentException("Unknown filter type " + filterType);
            }
        }

        return typeFilters;
    }

    private String[] getPatterns(AnnotationAttributes filterAttributes) {

        try {
            return filterAttributes.getStringArray("pattern");
        } catch (IllegalArgumentException o_O) {
            return new String[0];
        }
    }

}