1/* 2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23package org.graalvm.compiler.replacements.verifier; 24 25import java.lang.annotation.Annotation; 26 27import javax.annotation.processing.ProcessingEnvironment; 28import javax.lang.model.element.AnnotationMirror; 29import javax.lang.model.element.AnnotationValue; 30import javax.lang.model.element.Element; 31import javax.lang.model.element.TypeElement; 32import javax.lang.model.type.DeclaredType; 33import javax.lang.model.type.TypeKind; 34import javax.lang.model.type.TypeMirror; 35import javax.tools.Diagnostic.Kind; 36 37import org.graalvm.compiler.api.replacements.ClassSubstitution; 38 39public final class ClassSubstitutionVerifier extends AbstractVerifier { 40 41 private static final String TYPE_VALUE = "value"; 42 private static final String STRING_VALUE = "className"; 43 private static final String OPTIONAL = "optional"; 44 45 public ClassSubstitutionVerifier(ProcessingEnvironment env) { 46 super(env); 47 } 48 49 @Override 50 public Class<? extends Annotation> getAnnotationClass() { 51 return ClassSubstitution.class; 52 } 53 54 @Override 55 public void verify(Element element, AnnotationMirror classSubstitution, PluginGenerator generator) { 56 if (!element.getKind().isClass()) { 57 assert false : "Element is guaranteed to be a class."; 58 return; 59 } 60 TypeElement type = (TypeElement) element; 61 62 TypeElement substitutionType = resolveOriginalType(env, type, classSubstitution); 63 if (substitutionType == null) { 64 return; 65 } 66 } 67 68 static TypeElement resolveOriginalType(ProcessingEnvironment env, Element sourceElement, AnnotationMirror classSubstition) { 69 AnnotationValue typeValue = findAnnotationValue(classSubstition, TYPE_VALUE); 70 AnnotationValue stringValue = findAnnotationValue(classSubstition, STRING_VALUE); 71 AnnotationValue optionalValue = findAnnotationValue(classSubstition, OPTIONAL); 72 73 assert typeValue != null && stringValue != null && optionalValue != null; 74 75 TypeMirror type = resolveAnnotationValue(TypeMirror.class, typeValue); 76 String[] classNames = resolveAnnotationValue(String[].class, stringValue); 77 boolean optional = resolveAnnotationValue(Boolean.class, optionalValue); 78 79 if (type.getKind() != TypeKind.DECLARED) { 80 env.getMessager().printMessage(Kind.ERROR, "The provided class must be a declared type.", sourceElement, classSubstition, typeValue); 81 return null; 82 } 83 84 if (!classSubstition.getAnnotationType().asElement().equals(((DeclaredType) type).asElement())) { 85 if (classNames.length != 0) { 86 String msg = "The usage of value and className is exclusive."; 87 env.getMessager().printMessage(Kind.ERROR, msg, sourceElement, classSubstition, stringValue); 88 env.getMessager().printMessage(Kind.ERROR, msg, sourceElement, classSubstition, typeValue); 89 } 90 91 return (TypeElement) ((DeclaredType) type).asElement(); 92 } 93 94 if (classNames.length != 0) { 95 TypeElement typeElement = null; 96 for (String className : classNames) { 97 typeElement = env.getElementUtils().getTypeElement(className); 98 if (typeElement != null) { 99 break; 100 } 101 } 102 if (typeElement == null && !optional) { 103 env.getMessager().printMessage(Kind.ERROR, String.format("The class '%s' was not found on the classpath.", stringValue), sourceElement, classSubstition, stringValue); 104 } 105 106 return typeElement; 107 } 108 109 if (!optional) { 110 env.getMessager().printMessage(Kind.ERROR, String.format("No value for '%s' or '%s' provided but required.", TYPE_VALUE, STRING_VALUE), sourceElement, classSubstition); 111 } 112 113 return null; 114 } 115 116} 117