All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.thorstenmarx.modules.api.annotation.ExtensionAnnotationProcessor Maven / Gradle / Ivy

There is a newer version: 2.8.0
Show newest version
/**
 * ModuleManager
 * Copyright (C) 2016  ThorstenMarx ([email protected])
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.thorstenmarx.modules.api.annotation;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.MirroredTypesException;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic.Kind;
import javax.tools.FileObject;
import javax.tools.StandardLocation;

@SupportedAnnotationTypes("com.thorstenmarx.modules.api.annotation.Extension")
public class ExtensionAnnotationProcessor extends AbstractProcessor {

	@Override
	public SourceVersion getSupportedSourceVersion() {
		return SourceVersion.latest();
	}

	@Override
	public boolean process(Set annotations, RoundEnvironment roundEnv) {
		if (roundEnv.processingOver()) {
			return false;
		}
		Map> extensions = new HashMap<>();

		Elements elements = processingEnv.getElementUtils();

		roundEnv.getElementsAnnotatedWith(Extension.class).stream().forEach((e) -> {
			Extension a = e.getAnnotation(Extension.class);
			if (!(a == null)) {
				if (!(!e.getKind().isClass() && !e.getKind().isInterface())) {
					TypeElement typedElement = (TypeElement) e;
					Collection teCollection = getTypeElements(typedElement, a);
					teCollection.forEach((te) -> {
						String extensionName = elements.getBinaryName(te).toString();
						String extensionImplName = elements.getBinaryName(typedElement).toString();
						if (!extensions.containsKey(extensionName)) {
							extensions.put(extensionName, new TreeSet<>());
						}
						extensions.get(extensionName).add(extensionImplName);
					});
				}
			}
		});

		// load existing extensions
		final Filer filer = processingEnv.getFiler();
		extensions.entrySet().stream().forEach((e) -> {
			try {
				String contract = e.getKey();
				FileObject extensionFileObject = filer.getResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/services/" + contract);
				BufferedReader r = new BufferedReader(new InputStreamReader(extensionFileObject.openInputStream(), "UTF-8"));
				String line;
				while ((line = r.readLine()) != null) {
					e.getValue().add(line);
				}
				r.close();
			} catch (FileNotFoundException fnfe) {
				// no service file found
			} catch (IOException x) {
				processingEnv.getMessager().printMessage(Kind.ERROR, "Error loading existing extension files: " + x);
			}
		});

		// now write them back out
		extensions.entrySet().stream().forEach((e) -> {
			try {
				String extension = e.getKey();
				processingEnv.getMessager().printMessage(Kind.NOTE, "Creating META-INF/services/" + extension);
				FileObject f = filer.createResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/services/" + extension);
				PrintWriter pw = new PrintWriter(new OutputStreamWriter(f.openOutputStream(), "UTF-8"));
				for (String value : e.getValue()) {
					pw.println(value);
				}
				pw.close();
			} catch (IOException x) {
				processingEnv.getMessager().printMessage(Kind.ERROR, "Error creating extension file: " + x);
			}
		});

		return false;
	}

	private Collection getTypeElements(TypeElement type, Extension a) {
		List typeElements = new ArrayList<>();

		try {
			a.value();
		} catch (MirroredTypesException e) {

			e.getTypeMirrors().stream().forEach((m) -> {
				if (m instanceof DeclaredType) {
					DeclaredType dt = (DeclaredType) m;
					typeElements.add((TypeElement) dt.asElement());
				} else {
					processingEnv.getMessager().printMessage(Kind.ERROR, "Invalid type specified", type);
				}
			});
		}
		return typeElements;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy