blob: 6db5bae414135daddb127d8f89a84ff275c21f8e [file] [log] [blame]
/*
* 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;
}
}