org.duracloud.account.db.util.security.impl.AnnotationParserImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.duracloud.account.db.util.security.impl.AnnotationParserImpl.java

Source

/*
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 *     http://duracloud.org/license/
 */
package org.duracloud.account.db.util.security.impl;

import org.duracloud.account.db.util.security.AnnotationParser;
import org.duracloud.common.error.DuraCloudRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;

import java.io.IOException;
import java.util.*;

/**
 * This class provides a utility for searching through a class and its
 * hierarchy for a given annotation.
 * Once the methods with the given annotation are found, a mapping of the
 * method names and annotation argument values is returned.
 *
 * @author Andrew Woods
 *         Date: 4/8/11
 */
public class AnnotationParserImpl implements AnnotationParser {

    private Logger log = LoggerFactory.getLogger(AnnotationParserImpl.class);

    @Override
    public Map<String, Object[]> getMethodAnnotationsForClass(Class annotationClass, Class targetClass) {
        log.trace("Collecting annotations {} over {}", annotationClass.getName(), targetClass.getName());

        try {
            return doGetMethodAnnotationsForClass(annotationClass, targetClass);

        } catch (Exception e) {
            log.error("Error getting annotations {} over {}: {}",
                    new Object[] { annotationClass.getName(), targetClass.getName(), e.getMessage() });
            throw new DuraCloudRuntimeException(e);
        }
    }

    private Map<String, Object[]> doGetMethodAnnotationsForClass(Class annotationClass, Class targetClass) {
        Map<String, Object[]> methodAnnotations = new HashMap<String, Object[]>();

        // Find class/interface in stack that has the annotation
        Class iface = getAnnotatedInterface(annotationClass, targetClass);

        // Read the annotation metadata from the found class/interface
        MetadataReader metadataReader = getMetadataReader(iface);
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

        Set<MethodMetadata> annotatedMethods = getAnnotatedMethods(annotationMetadata, annotationClass);

        Iterator itr = getAnnotatedMethodsIterator(annotatedMethods);
        while (itr.hasNext()) {
            MethodMetadata methodMetadata = (MethodMetadata) itr.next();

            Map<String, Object> annotationAtts = methodMetadata.getAnnotationAttributes(annotationClass.getName());
            Object[] values = getValues(annotationAtts);
            methodAnnotations.put(methodMetadata.getMethodName(), values);
        }
        return methodAnnotations;
    }

    private Class getAnnotatedInterface(Class annotationClass, Class targetClass) {
        if (hasAnnotatedMethods(annotationClass, targetClass)) {
            return targetClass;
        }

        for (Class iface : targetClass.getInterfaces()) {
            if (hasAnnotatedMethods(annotationClass, iface)) {
                return iface;
            }
        }

        throw new DuraCloudRuntimeException(
                "No annotationMetadata found of " + annotationClass.getName() + " over " + targetClass.getName());
    }

    private boolean hasAnnotatedMethods(Class annotationClass, Class targetClass) {
        MetadataReader metadataReader = getMetadataReader(targetClass);
        AnnotationMetadata annotationMd = metadataReader.getAnnotationMetadata();
        return annotationMd.hasAnnotatedMethods(annotationClass.getName());
    }

    private MetadataReader getMetadataReader(Class<?> targetClass) {
        MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
        try {
            return metadataReaderFactory.getMetadataReader(targetClass.getName());

        } catch (IOException e) {
            log.warn("Error reading metadata. {}", e.getMessage());
            throw new DuraCloudRuntimeException(e);
        }
    }

    private Set<MethodMetadata> getAnnotatedMethods(AnnotationMetadata metadata, Class<?> annotationClass) {
        if (null == metadata) {
            throw new DuraCloudRuntimeException("Arg metadata is null: {}", annotationClass.getName());
        }
        return metadata.getAnnotatedMethods(annotationClass.getName());
    }

    private Iterator getAnnotatedMethodsIterator(Set<MethodMetadata> annotatedMethods) {
        if (null == annotatedMethods) {
            throw new DuraCloudRuntimeException("Arg annotatedMethods null.");
        }
        return annotatedMethods.iterator();
    }

    /**
     * This method extracts the annotation argument info from the annotation
     * metadata.
     * Since the implementation of access for annotation arguments varies, this
     * method may need to be overwritten by additional AnnotationParsers.
     *
     * @param annotationAtts mapping of annotation-implementation-dependent
     *                       access keys and the annotation arguments
     * @return array of the annotation arguments
     */
    private Object[] getValues(Map<String, Object> annotationAtts) {
        if (null == annotationAtts) {
            throw new DuraCloudRuntimeException("Arg annotationAtts is null.");
        }

        List<Object> values = new ArrayList<Object>();
        for (String key : annotationAtts.keySet()) {

            Object[] objects = (Object[]) annotationAtts.get(key);
            for (Object obj : objects) {
                values.add(obj);
            }
        }

        return values.toArray();
    }
}