ClassFileGsonDefinitionModelStore.java

  1. /*
  2.  * Copyright © 2017, Salesforce.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.apt.graph.model.storage.apt;

  28. import java.io.IOException;
  29. import java.io.OutputStream;
  30. import java.nio.charset.StandardCharsets;

  31. import javax.lang.model.element.Modifier;

  32. import com.google.gson.internal.JavaVersion;
  33. import com.salesforce.apt.graph.model.DefinitionModel;
  34. import com.salesforce.apt.graph.model.storage.DefinitionOutputStreamProvider;
  35. import com.salesforce.apt.graph.model.storage.ResourceLoader;
  36. import com.salesforce.apt.graph.model.storage.classpath.FileStore;
  37. import com.salesforce.apt.graph.model.storage.classpath.GsonDefinitionModelStore;
  38. import com.squareup.javapoet.AnnotationSpec;
  39. import com.squareup.javapoet.FieldSpec;
  40. import com.squareup.javapoet.JavaFile;
  41. import com.squareup.javapoet.TypeSpec;

  42. public class ClassFileGsonDefinitionModelStore extends GsonDefinitionModelStore {

  43.   private static final String GENERATED_JAVA9 = "javax.annotation.processing.Generated";

  44.   private static final String GENERATED_JAVA8 = "javax.annotation.Generated";

  45.  
  46.   public ClassFileGsonDefinitionModelStore(ResourceLoader resourceLocator, DefinitionOutputStreamProvider definitionModelToStore) {
  47.     super(resourceLocator, definitionModelToStore);
  48.   }
  49.  
  50.   @Override
  51.   public boolean store(DefinitionModel model) {
  52.     String packageName = model.getSourcePackage();
  53.     String className = model.getSourceClass() + "_" + FileStore.STANDARD.getPath();
  54.     String data = getGson().toJson(model);
  55.    
  56.     FieldSpec fieldSpec = FieldSpec.builder(String.class, AptResourceLoader.FIELD_NAME)
  57.         .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
  58.         .initializer("$S", data)
  59.         .addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "unused").build())
  60.         .build();

  61.     TypeSpec classSpec = TypeSpec.classBuilder(className)
  62.         .addModifiers(Modifier.PUBLIC)
  63.         .addField(fieldSpec)
  64.         .addAnnotation(AnnotationSpec.builder(getGeneratedAnnotationClass()).addMember("value", "$S", "SpringApt").build())
  65.         .build();
  66.    
  67.     JavaFile javaFile = JavaFile.builder(packageName, classSpec)
  68.         .build();

  69.     try {
  70.       OutputStream stream = getDefinitionOutputStreamProvider().store(model);
  71.       try {
  72.         stream.write(javaFile.toString().getBytes(StandardCharsets.UTF_8));
  73.       } finally {
  74.         stream.close();
  75.       }
  76.       model.setSha256(bytesToHex(getSha256Digest().digest(data.getBytes(StandardCharsets.UTF_8))));
  77.       return true;
  78.     } catch (IOException ex) {
  79.       throw new IllegalStateException("Could not store model to class", ex);
  80.     }
  81.   }
  82.  
  83.   private Class<?> getGeneratedAnnotationClass() {
  84.     final String generatedClass = JavaVersion.isJava9OrLater() ? GENERATED_JAVA9 : GENERATED_JAVA8;
  85.     try {
  86.       return Class.forName(generatedClass);
  87.     } catch (ClassNotFoundException ex) {
  88.       throw new RuntimeException(ex);
  89.     }
  90.   }
  91. }