VerifiedSpringConfiguration.java

  1. /*
  2.  * Copyright © 2017, Saleforce.com, Inc
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions are met:
  7.  *     * Redistributions of source code must retain the above copyright
  8.  *       notice, this list of conditions and the following disclaimer.
  9.  *     * Redistributions in binary form must reproduce the above copyright
  10.  *       notice, this list of conditions and the following disclaimer in the
  11.  *       documentation and/or other materials provided with the distribution.
  12.  *     * Neither the name of the <organization> nor the
  13.  *       names of its contributors may be used to endorse or promote products
  14.  *       derived from this software without specific prior written permission.
  15.  *
  16.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19.  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  20.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26.  */
  27. package com.salesforce.aptspring.processor;

  28. import java.io.PrintWriter;
  29. import java.io.StringWriter;
  30. import java.util.HashSet;
  31. import java.util.Set;

  32. import javax.annotation.processing.AbstractProcessor;
  33. import javax.annotation.processing.Filer;
  34. import javax.annotation.processing.Messager;
  35. import javax.annotation.processing.ProcessingEnvironment;
  36. import javax.annotation.processing.RoundEnvironment;
  37. import javax.annotation.processing.SupportedSourceVersion;
  38. import javax.lang.model.SourceVersion;
  39. import javax.lang.model.element.Element;
  40. import javax.lang.model.element.TypeElement;
  41. import javax.lang.model.util.Elements;
  42. import javax.lang.model.util.Types;
  43. import javax.tools.Diagnostic;

  44. import com.salesforce.apt.graph.model.errors.ErrorMessages;
  45. import com.salesforce.apt.graph.parser.apt.AptElementVisitor;
  46. import com.salesforce.apt.graph.parser.apt.AptParsingContext;
  47. import com.salesforce.aptspring.Verified;

  48. @SupportedSourceVersion(SourceVersion.RELEASE_8)
  49. public class VerifiedSpringConfiguration extends AbstractProcessor {

  50.   private Messager messager;
  51.  
  52.   private AptParsingContext definitionAggregator;

  53.   @Override
  54.   public synchronized void init(ProcessingEnvironment env) {
  55.     super.init(env);
  56.     Types typeUtils = env.getTypeUtils();
  57.     Elements elementUtils = env.getElementUtils();
  58.     Filer filer = env.getFiler();
  59.     messager = env.getMessager();
  60.     ErrorMessages errorMessages = ErrorMessages.builder()
  61.         .cycleInDefinitionSources("Cycle in @Imports {0}")
  62.         .cycleInObjectDefinitions("Cycle in spring bean dependencies {0}")
  63.         .duplicateObjectDefinitions("Duplicate in spring beans {0}")
  64.         .nonLiteralStaticMemberVariables("Non literal static member variables can break class instantiation and leak state")
  65.         .knownDamagingClass("Known damaging class import (contains non-literal static member variables)")
  66.         .missingBeanDefinitions("Missing bean definitions for spring beans {0},"
  67.            + " create definitions or list them in @Verified'''s expected field")
  68.         .missingRelevantAnnotations("Missing @Verified on classes {0}")
  69.         .unmatchedTypes("Unmatched types {0}")
  70.         .duplicatedMatchingDependencies("Duplicated matching dependencies {0}")
  71.         .duplicatedMatchingDefinitions("Duplicated matching definitions {0}")
  72.         .noMatchingDefinition("No matching definition {0}")
  73.         .unusedExpected("Expected bean name is unnecessary {0}")
  74.         .couldNotStore("Could not store incremental build file for {0}")
  75.         .couldNotRead("Could not read incremental build file for {0}")
  76.         .dependencyShaMismatch("Sha256 mismatch of dependency model of prior analyzed @Verified class model")
  77.         .rootNodeImported("@Verfied(root=true) may not be @Imported by other @Verified classes: {0}")
  78.         .build();
  79.     definitionAggregator = new AptParsingContext(errorMessages, filer, elementUtils, typeUtils);
  80.   }

  81.   @Override
  82.   public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
  83.     try  {
  84.       if (env.processingOver()) {
  85.         definitionAggregator.outputErrors(messager);
  86.       } else {
  87.         AptElementVisitor visitor = new AptElementVisitor(te -> new SpringAnnotationParser().extractDefinition(te, messager));
  88.         for (Element annotatedElement : env.getElementsAnnotatedWith(Verified.class)) {
  89.           visitor.visit(annotatedElement, definitionAggregator);        
  90.         }
  91.       }
  92.       return true;
  93.     } catch (Exception exception) {
  94.       // Catch and print for debugging reasons. This code path is unexpected.
  95.       StringWriter writer = new StringWriter();
  96.       exception.printStackTrace(new PrintWriter(writer));
  97.       messager.printMessage(Diagnostic.Kind.ERROR, writer.toString());
  98.       return true;
  99.     }
  100.   }

  101.   @Override
  102.   public Set<String> getSupportedAnnotationTypes() {
  103.     Set<String> output = new HashSet<>();
  104.     output.add(Verified.class.getName());
  105.     return output;
  106.   }
  107. }