# HG changeset patch # User Roland Schatz # Date 1364394138 -3600 # Node ID dc9cfb7ec5d03c22fa25d22eb57294a9a5de5ee5 # Parent 67f19ede48911bd8484d59e1b6b62d8535357029 Annotation processor for generating META-INF/services files. diff -r 67f19ede4891 -r dc9cfb7ec5d0 graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java Wed Mar 27 15:22:18 2013 +0100 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.runtime; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface ServiceProvider { + + Class value(); +} diff -r 67f19ede4891 -r dc9cfb7ec5d0 graal/com.oracle.graal.service.processor/src/META-INF/services/javax.annotation.processing.Processor --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.service.processor/src/META-INF/services/javax.annotation.processing.Processor Wed Mar 27 15:22:18 2013 +0100 @@ -0,0 +1,1 @@ +com.oracle.graal.service.processor.ServiceProviderProcessor diff -r 67f19ede4891 -r dc9cfb7ec5d0 graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java Wed Mar 27 15:22:18 2013 +0100 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.service.processor; + +import java.io.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.tools.Diagnostic.Kind; +import javax.tools.*; + +import com.oracle.graal.api.runtime.*; + +@SupportedSourceVersion(SourceVersion.RELEASE_7) +@SupportedAnnotationTypes("com.oracle.graal.api.runtime.ServiceProvider") +public class ServiceProviderProcessor extends AbstractProcessor { + + private Map> serviceMap; + + public ServiceProviderProcessor() { + serviceMap = new HashMap<>(); + } + + private void addProvider(String serviceName, TypeElement serviceProvider) { + Set providers = serviceMap.get(serviceName); + if (providers == null) { + providers = new HashSet<>(); + serviceMap.put(serviceName, providers); + } + providers.add(serviceProvider); + } + + private void generateServicesFiles() { + Filer filer = processingEnv.getFiler(); + for (Map.Entry> entry : serviceMap.entrySet()) { + String filename = "META-INF/services/" + entry.getKey(); + TypeElement[] providers = entry.getValue().toArray(new TypeElement[0]); + try { + FileObject servicesFile = filer.createResource(StandardLocation.CLASS_OUTPUT, "", filename, providers); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(servicesFile.openOutputStream(), "UTF-8")); + for (TypeElement provider : providers) { + writer.println(provider.getQualifiedName()); + } + writer.close(); + } catch (IOException e) { + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage()); + } + } + } + + private boolean verifyAnnotation(TypeMirror serviceInterface, TypeElement serviceProvider) { + if (!processingEnv.getTypeUtils().isSubtype(serviceProvider.asType(), serviceInterface)) { + String msg = String.format("Service provider class %s doesn't implement service interface %s", serviceProvider.getSimpleName(), serviceInterface); + processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider); + return false; + } + + return true; + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + generateServicesFiles(); + return true; + } + + for (Element element : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) { + assert element.getKind().isClass(); + ServiceProvider annotation = element.getAnnotation(ServiceProvider.class); + try { + annotation.value(); + } catch (MirroredTypeException ex) { + TypeMirror serviceInterface = ex.getTypeMirror(); + TypeElement serviceProvider = (TypeElement) element; + if (verifyAnnotation(serviceInterface, serviceProvider)) { + String interfaceName = ex.getTypeMirror().toString(); + addProvider(interfaceName, serviceProvider); + } + } + } + return true; + } +} diff -r 67f19ede4891 -r dc9cfb7ec5d0 mx/projects --- a/mx/projects Wed Mar 27 15:22:14 2013 +0100 +++ b/mx/projects Wed Mar 27 15:22:18 2013 +0100 @@ -65,6 +65,13 @@ project@com.oracle.graal.api.replacements@checkstyle=com.oracle.graal.graph project@com.oracle.graal.api.replacements@javaCompliance=1.7 +# graal.service.processor +project@com.oracle.graal.service.processor@subDir=graal +project@com.oracle.graal.service.processor@sourceDirs=src +project@com.oracle.graal.service.processor@dependencies=com.oracle.graal.api.runtime +project@com.oracle.graal.service.processor@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.service.processor@javaCompliance=1.7 + # graal.amd64 project@com.oracle.graal.amd64@subDir=graal project@com.oracle.graal.amd64@sourceDirs=src