1 /*
   2  * Copyright 2004 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any 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 public class AnnotationProcessorEnvironmentImpl implements AnnotationProcessorEnvironment {
  51 
  52     Collection<TypeDeclaration> spectypedecls;
  53     Collection<TypeDeclaration> typedecls;
  54     Map<String, String> origOptions;
  55     DeclarationMaker declMaker;
  56     Declarations declUtils;
  57     Types typeUtils;
  58     Messager messager;
  59     FilerImpl filer;
  60     Bark bark;
  61     Set<RoundCompleteListener> roundCompleteListeners;
  62 
  63     public AnnotationProcessorEnvironmentImpl(Collection<TypeDeclaration> spectypedecls,
  64                                               Collection<TypeDeclaration> typedecls,
  65                                               Map<String, String> origOptions,
  66                                               Context context) {
  67         // Safer to copy collections before applying unmodifiable
  68         // wrapper.
  69         this.spectypedecls = Collections.unmodifiableCollection(spectypedecls);
  70         this.typedecls = Collections.unmodifiableCollection(typedecls);
  71         this.origOptions = Collections.unmodifiableMap(origOptions);
  72 
  73         declMaker = DeclarationMaker.instance(context);
  74         declUtils = DeclarationsImpl.instance(context);
  75         typeUtils = TypesImpl.instance(context);
  76         messager = MessagerImpl.instance(context);
  77         filer = FilerImpl.instance(context);
  78         bark = Bark.instance(context);
  79         roundCompleteListeners = new LinkedHashSet<RoundCompleteListener>();
  80     }
  81 
  82     public Map<String,String> getOptions() {
  83         return origOptions;
  84     }
  85 
  86     public Messager getMessager() {
  87         return messager;
  88     }
  89 
  90     public Filer getFiler() {
  91         return filer;
  92     }
  93 
  94     public Collection<TypeDeclaration> getSpecifiedTypeDeclarations() {
  95         return spectypedecls;
  96     }
  97 
  98     public PackageDeclaration getPackage(String name) {
  99         return declMaker.getPackageDeclaration(name);
 100     }
 101 
 102     public TypeDeclaration getTypeDeclaration(String name) {
 103         return declMaker.getTypeDeclaration(name);
 104     }
 105 
 106     public Collection<TypeDeclaration> getTypeDeclarations() {
 107         return typedecls;
 108     }
 109 
 110     public Collection<Declaration> getDeclarationsAnnotatedWith(
 111                                                 AnnotationTypeDeclaration a) {
 112         /*
 113          * create collection of Declarations annotated with a given
 114          * annotation.
 115          */
 116 
 117         CollectingAP proc = new CollectingAP(this, a);
 118         proc.process();
 119         return proc.decls;
 120     }
 121 
 122     private static class CollectingAP implements AnnotationProcessor {
 123         AnnotationProcessorEnvironment env;
 124         Collection<Declaration> decls;
 125         AnnotationTypeDeclaration atd;
 126         CollectingAP(AnnotationProcessorEnvironment env,
 127                      AnnotationTypeDeclaration atd) {
 128             this.env = env;
 129             this.atd = atd;
 130             decls = new HashSet<Declaration>();
 131         }
 132 
 133         private class CollectingVisitor extends SimpleDeclarationVisitor {
 134             public void visitDeclaration(Declaration d) {
 135                 for(AnnotationMirror am: d.getAnnotationMirrors()) {
 136                     if (am.getAnnotationType().getDeclaration().equals(CollectingAP.this.atd))
 137                         CollectingAP.this.decls.add(d);
 138                 }
 139             }
 140         }
 141 
 142         public void process() {
 143             for(TypeDeclaration d: env.getSpecifiedTypeDeclarations())
 144                 d.accept(getSourceOrderDeclarationScanner(new CollectingVisitor(),
 145                                                           NO_OP));
 146         }
 147     }
 148 
 149     public Declarations getDeclarationUtils() {
 150         return declUtils;
 151     }
 152 
 153     public Types getTypeUtils() {
 154         return typeUtils;
 155     }
 156 
 157     public void addListener(AnnotationProcessorListener listener) {
 158         if (listener == null)
 159             throw new NullPointerException();
 160         else {
 161             if (listener instanceof RoundCompleteListener)
 162                 roundCompleteListeners.add((RoundCompleteListener)listener);
 163         }
 164     }
 165 
 166     public void removeListener(AnnotationProcessorListener listener) {
 167         if (listener == null)
 168             throw new NullPointerException();
 169         else
 170             roundCompleteListeners.remove(listener);
 171     }
 172 
 173     public void roundComplete() {
 174         RoundState roundState  = new RoundStateImpl(bark.nerrors > 0,
 175                                                     filer.getSourceFileNames().size() > 0,
 176                                                     filer.getClassFileNames().size() > 0,
 177                                                     origOptions);
 178         RoundCompleteEvent roundCompleteEvent = new RoundCompleteEventImpl(this, roundState);
 179 
 180         filer.roundOver();
 181         for(RoundCompleteListener rcl: roundCompleteListeners)
 182             rcl.roundComplete(roundCompleteEvent);
 183     }
 184 }