/* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This source code is provided to illustrate the usage of a given feature * or technique and has been deliberately simplified. Additional steps * required for a production-quality application, such as security checks, * input validation and proper error handling, might not be present in * this sample code. */ package checker; import javax.annotation.processing.ProcessingEnvironment; 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.tools.Diagnostic; import javax.xml.bind.JAXBContext; import java.io.File; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import javax.xml.bind.JAXBException; /** * Reads the device configuration from the XML file specified by -Adevice=device.xml. * For each class in a project, checks required modules. If the device doesn't have * the required module, then a compilation error will be shown. */ @SupportedAnnotationTypes("checker.RequireContainer") @SupportedSourceVersion(SourceVersion.RELEASE_8) public class PluginChecker extends javax.annotation.processing.AbstractProcessor { /** * Name of the option to get the path to the xml with device configuration. */ public static final String DEVICE_OPTION = "device"; private Device device; /** * Only the device option is supported. * * {@inheritDoc} */ @Override public Set<String> getSupportedOptions() { return new HashSet<>(Arrays.asList(DEVICE_OPTION)); } /** * Initializes the processor by loading the device configuration. * * {@inheritDoc} */ @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); try { String deviceOption = processingEnv.getOptions().get(DEVICE_OPTION); device = (Device) JAXBContext.newInstance(Device.class) .createUnmarshaller().unmarshal(new File(deviceOption)); } catch (JAXBException e) { throw new RuntimeException( "Please specify device by -Adevice=device.xml\n" + e.toString(), e); } } /** * Processes @Require annotations and checks that Device meets requirements. * * {@inheritDoc} */ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { for (Element el : roundEnv.getElementsAnnotatedWith(RequireContainer.class)) { for (Require req : el.getAnnotationsByType(Require.class)) { //for every Require annotation checks if device has module of required version. Integer version = device.getSupportedModules().get(req.value()); if (version == null || version < req.minVersion() || version > req.maxVersion()) { //if module is optional then show only warning not error if (req.optional()) { processingEnv.getMessager() .printMessage(Diagnostic.Kind.WARNING, "Plugin [" + el + "] requires " + req + "\n but device " + (version == null ? "doesn't have such module." + " This module is optional." + " So plugin will work but miss" + " some functionality" : "has " + version + " version of that module")); } else { processingEnv.getMessager() .printMessage(Diagnostic.Kind.ERROR, "Plugin [" + el + "] requires " + req + "\n but device " + (version == null ? "doesn't have such module" : "has " + version + " version of that module")); } } } return true; } return false; } }