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.lang.reflect.*;
027import java.util.*;
028
029import javax.annotation.processing.*;
030import javax.lang.model.element.*;
031import javax.lang.model.type.*;
032import javax.lang.model.util.*;
033
034public abstract class AbstractVerifier {
035
036    protected final ProcessingEnvironment env;
037
038    public AbstractVerifier(ProcessingEnvironment env) {
039        this.env = env;
040    }
041
042    public abstract void verify(Element element, AnnotationMirror annotation);
043
044    public abstract Class<? extends Annotation> getAnnotationClass();
045
046    @SuppressWarnings("unchecked")
047    protected static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
048        if (value == null) {
049            return null;
050        }
051        if (expectedType.isArray()) {
052            ArrayList<Object> result = new ArrayList<>();
053            List<AnnotationValue> l = (List<AnnotationValue>) value.getValue();
054            for (AnnotationValue el : l) {
055                result.add(resolveAnnotationValue(expectedType.getComponentType(), el));
056            }
057            return (T) result.toArray((Object[]) Array.newInstance(expectedType.getComponentType(), result.size()));
058        }
059        Object unboxedValue = value.getValue();
060        if (unboxedValue != null) {
061            if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
062                /*
063                 * Happens if type is invalid when using the ECJ compiler. The ECJ does not match
064                 * AP-API specification here.
065                 */
066                return null;
067            }
068            if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
069                throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
070            }
071        }
072        return (T) unboxedValue;
073    }
074
075    protected static AnnotationValue findAnnotationValue(AnnotationMirror mirror, String name) {
076        ExecutableElement valueMethod = null;
077        for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
078            if (method.getSimpleName().toString().equals(name)) {
079                valueMethod = method;
080                break;
081            }
082        }
083
084        if (valueMethod == null) {
085            return null;
086        }
087
088        AnnotationValue value = mirror.getElementValues().get(valueMethod);
089        if (value == null) {
090            value = valueMethod.getDefaultValue();
091        }
092
093        return value;
094    }
095
096}