1 /*
   2  * Copyright (c) 2004, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.apt.mirror.apt;
  27 
  28 import com.sun.mirror.declaration.*;
  29 import com.sun.mirror.util.*;
  30 import com.sun.mirror.apt.*;
  31 import com.sun.tools.apt.mirror.apt.*;
  32 import com.sun.tools.apt.mirror.declaration.DeclarationMaker;
  33 import com.sun.tools.apt.mirror.util.*;
  34 import com.sun.tools.apt.util.Bark;
  35 import com.sun.tools.javac.util.Context;
  36 
  37 import com.sun.tools.apt.mirror.apt.FilerImpl;
  38 import com.sun.tools.apt.mirror.apt.MessagerImpl;
  39 import com.sun.tools.apt.mirror.apt.RoundStateImpl;
  40 import com.sun.tools.apt.mirror.apt.RoundCompleteEventImpl;
  41 
  42 import com.sun.tools.javac.util.Context;
  43 
  44 import java.util.*;
  45 import static com.sun.mirror.util.DeclarationVisitors.*;
  46 
  47 /*
  48  * Annotation Processor Environment implementation.
  49  */
  50 @SuppressWarnings("deprecation")
  51 public class AnnotationProcessorEnvironmentImpl implements AnnotationProcessorEnvironment {
  52 
  53     Collection<TypeDeclaration> spectypedecls;
  54     Collection<TypeDeclaration> typedecls;
  55     Map<String, String> origOptions;
  56     DeclarationMaker declMaker;
  57     Declarations declUtils;
  58     Types typeUtils;
  59     Messager messager;
  60     FilerImpl filer;
  61     Bark bark;
  62     Set<RoundCompleteListener> roundCompleteListeners;
  63 
  64     public AnnotationProcessorEnvironmentImpl(Collection<TypeDeclaration> spectypedecls,
  65                                               Collection<TypeDeclaration> typedecls,
  66                                               Map<String, String> origOptions,
  67                                               Context context) {
  68         // Safer to copy collections before applying unmodifiable
  69         // wrapper.
  70         this.spectypedecls = Collections.unmodifiableCollection(spectypedecls);
  71         this.typedecls = Collections.unmodifiableCollection(typedecls);
  72         this.origOptions = Collections.unmodifiableMap(origOptions);
  73 
  74         declMaker = DeclarationMaker.instance(context);
  75         declUtils = DeclarationsImpl.instance(context);
  76         typeUtils = TypesImpl.instance(context);
  77         messager = MessagerImpl.instance(context);
  78         filer = FilerImpl.instance(context);
  79         bark = Bark.instance(context);
  80         roundCompleteListeners = new LinkedHashSet<RoundCompleteListener>();
  81     }
  82 
  83     public Map<String,String> getOptions() {
  84         return origOptions;
  85     }
  86 
  87     public Messager getMessager() {
  88         return messager;
  89     }
  90 
  91     public Filer getFiler() {
  92         return filer;
  93     }
  94 
  95     public Collection<TypeDeclaration> getSpecifiedTypeDeclarations() {
  96         return spectypedecls;
  97     }
  98 
  99     public PackageDeclaration getPackage(String name) {
 100         return declMaker.getPackageDeclaration(name);
 101     }
 102 
 103     public TypeDeclaration getTypeDeclaration(String name) {
 104         return declMaker.getTypeDeclaration(name);
 105     }
 106 
 107     public Collection<TypeDeclaration> getTypeDeclarations() {
 108         return typedecls;
 109     }
 110 
 111     public Collection<Declaration> getDeclarationsAnnotatedWith(
 112                                                 AnnotationTypeDeclaration a) {
 113         /*
 114          * create collection of Declarations annotated with a given
 115          * annotation.
 116          */
 117 
 118         CollectingAP proc = new CollectingAP(this, a);
 119         proc.process();
 120         return proc.decls;
 121     }
 122 
 123     private static class CollectingAP implements AnnotationProcessor {
 124         AnnotationProcessorEnvironment env;
 125         Collection<Declaration> decls;
 126         AnnotationTypeDeclaration atd;
 127         CollectingAP(AnnotationProcessorEnvironment env,
 128                      AnnotationTypeDeclaration atd) {
 129             this.env = env;
 130             this.atd = atd;
 131             decls = new HashSet<Declaration>();
 132         }
 133 
 134         private class CollectingVisitor extends SimpleDeclarationVisitor {
 135             public void visitDeclaration(Declaration d) {
 136                 for(AnnotationMirror am: d.getAnnotationMirrors()) {
 137                     if (am.getAnnotationType().getDeclaration().equals(CollectingAP.this.atd))
 138                         CollectingAP.this.decls.add(d);
 139                 }
 140             }
 141         }
 142 
 143         public void process() {
 144             for(TypeDeclaration d: env.getSpecifiedTypeDeclarations())
 145                 d.accept(getSourceOrderDeclarationScanner(new CollectingVisitor(),
 146                                                           NO_OP));
 147         }
 148     }
 149 
 150     public Declarations getDeclarationUtils() {
 151         return declUtils;
 152     }
 153 
 154     public Types getTypeUtils() {
 155         return typeUtils;
 156     }
 157 
 158     public void addListener(AnnotationProcessorListener listener) {
 159         if (listener == null)
 160             throw new NullPointerException();
 161         else {
 162             if (listener instanceof RoundCompleteListener)
 163                 roundCompleteListeners.add((RoundCompleteListener)listener);
 164         }
 165     }
 166 
 167     public void removeListener(AnnotationProcessorListener listener) {
 168         if (listener == null)
 169             throw new NullPointerException();
 170         else
 171             roundCompleteListeners.remove(listener);
 172     }
 173 
 174     public void roundComplete() {
 175         RoundState roundState  = new RoundStateImpl(bark.nerrors > 0,
 176                                                     filer.getSourceFileNames().size() > 0,
 177                                                     filer.getClassFileNames().size() > 0,
 178                                                     origOptions);
 179         RoundCompleteEvent roundCompleteEvent = new RoundCompleteEventImpl(this, roundState);
 180 
 181         filer.roundOver();
 182         for(RoundCompleteListener rcl: roundCompleteListeners)
 183             rcl.roundComplete(roundCompleteEvent);
 184     }
 185 }