1 /*
   2  * Copyright (c) 2009, 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.  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.javac.code;
  27 
  28 import java.util.Collections;
  29 import java.util.EnumSet;
  30 import java.util.Locale;
  31 import java.util.Set;
  32 
  33 import javax.lang.model.element.ModuleElement;
  34 import javax.lang.model.element.ModuleElement.DirectiveVisitor;
  35 
  36 import com.sun.tools.javac.api.Messages;
  37 import com.sun.tools.javac.code.Symbol.ClassSymbol;
  38 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
  39 import com.sun.tools.javac.code.Symbol.PackageSymbol;
  40 import com.sun.tools.javac.util.DefinedBy;
  41 import com.sun.tools.javac.util.DefinedBy.Api;
  42 import com.sun.tools.javac.util.List;
  43 
  44 
  45 /**
  46  *  Root class for the directives that may appear in module compilation units.
  47  *
  48  *  <p><b>This is NOT part of any supported API.
  49  *  If you write code that depends on this, you do so at your own risk.
  50  *  This code and its internal interfaces are subject to change or
  51  *  deletion without notice.</b>
  52  */
  53 public abstract class Directive implements ModuleElement.Directive {
  54 
  55     /** Flags for RequiresDirective. */
  56     public enum RequiresFlag {
  57         TRANSITIVE(0x0020),
  58         STATIC_PHASE(0x0040),
  59         SYNTHETIC(0x1000),
  60         MANDATED(0x8000),
  61         EXTRA(0x10000);
  62 
  63         // overkill? move to ClassWriter?
  64         public static int value(Set<RequiresFlag> s) {
  65             int v = 0;
  66             for (RequiresFlag f: s)
  67                 v |= f.value;
  68             return v;
  69         }
  70 
  71         RequiresFlag(int value) {
  72             this.value = value;
  73         }
  74 
  75         public final int value;
  76 
  77         @Override
  78         public String toString() {
  79             return String.format("ACC_%s (0x%04x", name(), value);
  80         }
  81     }
  82 
  83     /** Flags for ExportsDirective. */
  84     public enum ExportsFlag {
  85         SYNTHETIC(0x1000),
  86         MANDATED(0x8000);
  87 
  88         // overkill? move to ClassWriter?
  89         public static int value(Set<ExportsFlag> s) {
  90             int v = 0;
  91             for (ExportsFlag f: s)
  92                 v |= f.value;
  93             return v;
  94         }
  95 
  96         ExportsFlag(int value) {
  97             this.value = value;
  98         }
  99 
 100         public final int value;
 101     }
 102 
 103     /**
 104      * 'exports' Package ';'
 105      * 'exports' Package 'to' ModuleList ';'
 106      */
 107     public static class ExportsDirective extends Directive
 108             implements ModuleElement.ExportsDirective {
 109         public final PackageSymbol packge;
 110         public final List<ModuleSymbol> modules;
 111         public final Set<ExportsFlag> flags;
 112 
 113         public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
 114             this(packge, modules, EnumSet.noneOf(ExportsFlag.class));
 115         }
 116 
 117         public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<ExportsFlag> flags) {
 118             this.packge = packge;
 119             this.modules = modules;
 120             this.flags = flags;
 121         }
 122 
 123         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 124         public ModuleElement.DirectiveKind getKind() {
 125             return ModuleElement.DirectiveKind.EXPORTS;
 126         }
 127 
 128         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 129         public PackageSymbol getPackage() {
 130             return packge;
 131         }
 132 
 133         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 134         public java.util.List<ModuleSymbol> getTargetModules() {
 135             return modules == null
 136                     ? null
 137                     : Collections.unmodifiableList(modules);
 138         }
 139 
 140         @Override
 141         public String toString() {
 142             if (modules == null)
 143                 return "Exports[" + packge + "]";
 144             else
 145                 return "Exports[" + packge + ":" + modules + "]";
 146         }
 147 
 148         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 149         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
 150             return v.visitExports(this, p);
 151         }
 152     }
 153 
 154     /** Flags for OpensDirective. */
 155     public enum OpensFlag {
 156         SYNTHETIC(0x1000),
 157         MANDATED(0x8000);
 158 
 159         // overkill? move to ClassWriter?
 160         public static int value(Set<OpensFlag> s) {
 161             int v = 0;
 162             for (OpensFlag f: s)
 163                 v |= f.value;
 164             return v;
 165         }
 166 
 167         OpensFlag(int value) {
 168             this.value = value;
 169         }
 170 
 171         public final int value;
 172     }
 173 
 174     /**
 175      * 'opens' Package ';'
 176      * 'opens' Package 'to' ModuleList ';'
 177      */
 178     public static class OpensDirective extends Directive
 179             implements ModuleElement.OpensDirective {
 180         public final PackageSymbol packge;
 181         public final List<ModuleSymbol> modules;
 182         public final Set<OpensFlag> flags;
 183 
 184         public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
 185             this(packge, modules, EnumSet.noneOf(OpensFlag.class));
 186         }
 187 
 188         public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<OpensFlag> flags) {
 189             this.packge = packge;
 190             this.modules = modules;
 191             this.flags = flags;
 192         }
 193 
 194         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 195         public ModuleElement.DirectiveKind getKind() {
 196             return ModuleElement.DirectiveKind.OPENS;
 197         }
 198 
 199         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 200         public PackageSymbol getPackage() {
 201             return packge;
 202         }
 203 
 204         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 205         public java.util.List<ModuleSymbol> getTargetModules() {
 206             return modules == null
 207                     ? null
 208                     : Collections.unmodifiableList(modules);
 209         }
 210 
 211         @Override
 212         public String toString() {
 213             if (modules == null)
 214                 return "Opens[" + packge + "]";
 215             else
 216                 return "Opens[" + packge + ":" + modules + "]";
 217         }
 218 
 219         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 220         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
 221             return v.visitOpens(this, p);
 222         }
 223     }
 224 
 225     /**
 226      * 'provides' ServiceName 'with' QualifiedIdentifier ';'
 227      */
 228     public static class ProvidesDirective extends Directive
 229             implements ModuleElement.ProvidesDirective {
 230         public final ClassSymbol service;
 231         public final List<ClassSymbol> impls;
 232 
 233         public ProvidesDirective(ClassSymbol service, List<ClassSymbol> impls) {
 234             this.service = service;
 235             this.impls = impls;
 236         }
 237 
 238         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 239         public ModuleElement.DirectiveKind getKind() {
 240             return ModuleElement.DirectiveKind.PROVIDES;
 241         }
 242 
 243         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 244         public ClassSymbol getService() {
 245             return service;
 246         }
 247 
 248         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 249         public List<ClassSymbol> getImplementations() {
 250             return impls;
 251         }
 252 
 253         @Override
 254         public String toString() {
 255             return "Provides[" + service + "," + impls + "]";
 256         }
 257 
 258         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 259         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
 260             return v.visitProvides(this, p);
 261         }
 262 
 263         // TODO: delete?
 264         @Override
 265         public boolean equals(Object obj) {
 266             if (!(obj instanceof ProvidesDirective)) {
 267                 return false;
 268             }
 269             ProvidesDirective other = (ProvidesDirective)obj;
 270             return service == other.service && impls.equals(other.impls);
 271         }
 272 
 273         // TODO: delete?
 274         @Override
 275         public int hashCode() {
 276             return service.hashCode() * 31 + impls.hashCode() * 37;
 277         }
 278     }
 279 
 280     /**
 281      * 'requires' ('static' | 'transitive')* ModuleName ';'
 282      */
 283     public static class RequiresDirective extends Directive
 284             implements ModuleElement.RequiresDirective {
 285         public final ModuleSymbol module;
 286         public final Set<RequiresFlag> flags;
 287 
 288         public RequiresDirective(ModuleSymbol module) {
 289             this(module, EnumSet.noneOf(RequiresFlag.class));
 290         }
 291 
 292         public RequiresDirective(ModuleSymbol module, Set<RequiresFlag> flags) {
 293             this.module = module;
 294             this.flags = flags;
 295         }
 296 
 297         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 298         public ModuleElement.DirectiveKind getKind() {
 299             return ModuleElement.DirectiveKind.REQUIRES;
 300         }
 301 
 302         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 303         public boolean isStatic() {
 304             return flags.contains(RequiresFlag.STATIC_PHASE);
 305         }
 306 
 307         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 308         public boolean isTransitive() {
 309             return flags.contains(RequiresFlag.TRANSITIVE);
 310         }
 311 
 312         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 313         public ModuleSymbol getDependency() {
 314             return module;
 315         }
 316 
 317         @Override
 318         public String toString() {
 319             return "Requires[" + flags + "," + module + "]";
 320         }
 321 
 322         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 323         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
 324             return v.visitRequires(this, p);
 325         }
 326     }
 327 
 328     /**
 329      * 'uses' ServiceName ';'
 330      */
 331     public static class UsesDirective extends Directive
 332             implements ModuleElement.UsesDirective {
 333         public final ClassSymbol service;
 334 
 335         public UsesDirective(ClassSymbol service) {
 336             this.service = service;
 337         }
 338 
 339         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 340         public ModuleElement.DirectiveKind getKind() {
 341             return ModuleElement.DirectiveKind.USES;
 342         }
 343 
 344         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 345         public ClassSymbol getService() {
 346             return service;
 347         }
 348 
 349         @Override
 350         public String toString() {
 351             return "Uses[" + service + "]";
 352         }
 353 
 354         @Override @DefinedBy(Api.LANGUAGE_MODEL)
 355         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
 356             return v.visitUses(this, p);
 357         }
 358 
 359         // TODO: delete?
 360         @Override
 361         public boolean equals(Object obj) {
 362             if (!(obj instanceof UsesDirective)) {
 363                 return false;
 364             }
 365             UsesDirective other = (UsesDirective)obj;
 366             return service == other.service;
 367         }
 368 
 369         // TODO: delete?
 370         @Override
 371         public int hashCode() {
 372             return service.hashCode() * 31;
 373         }
 374     }
 375 }