001/*
002 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.replacements.verifier;
024
025import java.lang.annotation.*;
026import java.util.*;
027
028import javax.annotation.processing.*;
029import javax.lang.model.*;
030import javax.lang.model.element.*;
031import javax.lang.model.type.*;
032
033public class VerifierAnnotationProcessor extends AbstractProcessor {
034
035    private List<AbstractVerifier> verifiers;
036
037    @Override
038    public SourceVersion getSupportedSourceVersion() {
039        return SourceVersion.latest();
040    }
041
042    @Override
043    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
044        if (!roundEnv.processingOver()) {
045            for (AbstractVerifier verifier : getVerifiers()) {
046                Class<? extends Annotation> annotationClass = verifier.getAnnotationClass();
047                for (Element e : roundEnv.getElementsAnnotatedWith(annotationClass)) {
048                    AnnotationMirror annotationMirror = findAnnotationMirror(processingEnv, e.getAnnotationMirrors(), annotationClass);
049                    if (annotationMirror == null) {
050                        assert false : "Annotation mirror always expected.";
051                        continue;
052                    }
053                    verifier.verify(e, annotationMirror);
054                }
055            }
056        }
057        return false;
058    }
059
060    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
061        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
062        for (AnnotationMirror mirror : mirrors) {
063            DeclaredType annotationType = mirror.getAnnotationType();
064            TypeElement actualAnnotationType = (TypeElement) annotationType.asElement();
065            if (actualAnnotationType.equals(expectedAnnotationType)) {
066                return mirror;
067            }
068        }
069        return null;
070    }
071
072    public List<AbstractVerifier> getVerifiers() {
073        /* Initialized lazily to fail(CNE) when the processor is invoked and not when it is created. */
074        if (verifiers == null) {
075            assert this.processingEnv != null : "ProcessingEnv must be initialized before calling getVerifiers.";
076            verifiers = new ArrayList<>();
077            verifiers.add(new ClassSubstitutionVerifier(this.processingEnv));
078            verifiers.add(new MethodSubstitutionVerifier(this.processingEnv));
079            verifiers.add(new NodeIntrinsicVerifier(this.processingEnv));
080        }
081        return verifiers;
082    }
083
084    @Override
085    public Set<String> getSupportedAnnotationTypes() {
086        Set<String> annotationTypes = new HashSet<>();
087        for (AbstractVerifier verifier : getVerifiers()) {
088            annotationTypes.add(verifier.getAnnotationClass().getCanonicalName());
089        }
090        return annotationTypes;
091    }
092
093}