1 /*
   2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package vm.mlvm.tools;
  25 
  26 import java.io.IOException;
  27 import java.io.Writer;
  28 import java.util.Set;
  29 import java.io.File;
  30 
  31 import javax.annotation.processing.AbstractProcessor;
  32 import javax.annotation.processing.Filer;
  33 import javax.annotation.processing.ProcessingEnvironment;
  34 import javax.annotation.processing.RoundEnvironment;
  35 import javax.annotation.processing.SupportedAnnotationTypes;
  36 import javax.annotation.processing.SupportedSourceVersion;
  37 import javax.lang.model.SourceVersion;
  38 import javax.lang.model.element.Element;
  39 import javax.lang.model.element.TypeElement;
  40 import javax.tools.FileObject;
  41 import javax.tools.StandardLocation;
  42 
  43 import nsk.share.jdi.sde.SmapGenerator;
  44 import nsk.share.jdi.sde.SmapStratum;
  45 import vm.mlvm.share.Stratum;
  46 import vm.mlvm.tools.StratumAPTreeVisitor.StratumLineInfo;
  47 
  48 import com.sun.source.tree.CompilationUnitTree;
  49 import com.sun.source.util.TreePath;
  50 import com.sun.source.util.Trees;
  51 
  52 @SupportedAnnotationTypes("vm.mlvm.share.Stratum")
  53 public class StratumAP extends AbstractProcessor {
  54 
  55     public static final String SMAP_EXT = ".smap";
  56     private boolean verbose = false;
  57 
  58     private Trees trees;
  59     @Override
  60     public synchronized void init(ProcessingEnvironment processingEnv) {
  61         super.init(processingEnv);
  62         trees = Trees.instance(processingEnv);
  63         verbose = Boolean.parseBoolean(processingEnv.getOptions().get("verbose"));
  64     }
  65 
  66     public SourceVersion getSupportedSourceVersion() {
  67         return SourceVersion.latest();
  68     }
  69 
  70     @Override
  71     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
  72         if (roundEnv.processingOver()) {
  73             return true;
  74         }
  75 
  76         for (Element e : roundEnv.getElementsAnnotatedWith(Stratum.class)) {
  77             Stratum s = e.getAnnotation(Stratum.class);
  78             if (s == null) {
  79                 continue;
  80             }
  81 
  82             TreePath tp = trees.getPath(e);
  83 
  84             StratumAPTreeVisitor visitor = new StratumAPTreeVisitor();
  85             visitor.scan(tp, trees);
  86 
  87             String stratumName = s.stratumName();
  88             String stratumSourceFileName = s.stratumSourceFileName();
  89 
  90             SmapStratum st = new SmapStratum(stratumName);
  91             st.addFile(stratumSourceFileName);
  92 
  93             Set<StratumLineInfo> lines = visitor.strata.get(stratumName);
  94             StringBuffer stratumSource = new StringBuffer();
  95             if (lines != null) {
  96                 int curStratumLine = 1;
  97                 for (StratumLineInfo lineInfo : lines) {
  98                     for (int i = -1; i <= 1; i++)
  99                         st.addLineData(curStratumLine,
 100                                        stratumSourceFileName,
 101                                        1,
 102                                        lineInfo.getJavaLineNum() + i,
 103                                        1);
 104 
 105                     stratumSource.append(lineInfo.getStratumSourceLine()).append("\n");
 106                     ++curStratumLine;
 107                 }
 108             }
 109 
 110             if (verbose) {
 111                 System.out.println("Strata:\n" + visitor.strata + "\n\nSource:\n" + stratumSource);
 112             }
 113 
 114             CompilationUnitTree compUnit = tp.getCompilationUnit();
 115             String pkgName = compUnit.getPackageName().toString();
 116             Filer filer = processingEnv.getFiler();
 117 
 118             SmapGenerator gen = new SmapGenerator();
 119             gen.addStratum(st, false);
 120 
 121             try {
 122                 FileObject stratumFile = filer.createResource(StandardLocation.CLASS_OUTPUT, pkgName, stratumSourceFileName, e);
 123 
 124                 if (verbose) {
 125                     System.out.println("Writing " + stratumFile.toUri());
 126                 }
 127 
 128                 Writer writer = stratumFile.openWriter();
 129                 try {
 130                     writer.append(stratumSource);
 131                 } finally {
 132                     writer.close();
 133                 }
 134             } catch (IOException ioe) {
 135                 ioe.printStackTrace();
 136                 return false;
 137             }
 138 
 139             String sourceFileName =
 140                 compUnit.getSourceFile().getName()
 141                 .replaceAll("^.*\\" + File.separatorChar, "");
 142 
 143             gen.setOutputFileName(sourceFileName);
 144 
 145             if (verbose) {
 146                 System.out.println(gen.getString() + "\n");
 147             }
 148 
 149             String smapFileName =
 150                 sourceFileName
 151                 .replaceAll("\\..*$", "")
 152                 + SMAP_EXT;
 153 
 154             try {
 155                 FileObject smapFile = filer.createResource(StandardLocation.CLASS_OUTPUT, pkgName, smapFileName, e);
 156 
 157                 if (verbose) {
 158                     System.out.println("Writing " + smapFile.toUri());
 159                 }
 160 
 161                 Writer writer = smapFile.openWriter();
 162                 try {
 163                     writer.append(gen.getString());
 164                 } finally {
 165                     writer.close();
 166                 }
 167             } catch (IOException ioe) {
 168                 ioe.printStackTrace();
 169                 return false;
 170             }
 171         }
 172 
 173         return true;
 174     }
 175 }