langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java
changeset 44291 e1b620ac6c98
parent 43368 cabe410a7a5c
child 45504 ea7475564d07
equal deleted inserted replaced
44290:202973b2d1ae 44291:e1b620ac6c98
     1 /*
     1 /*
     2  * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    58 import com.sun.tools.javac.model.JavacElements;
    58 import com.sun.tools.javac.model.JavacElements;
    59 import com.sun.tools.javac.util.*;
    59 import com.sun.tools.javac.util.*;
    60 import com.sun.tools.javac.util.DefinedBy.Api;
    60 import com.sun.tools.javac.util.DefinedBy.Api;
    61 
    61 
    62 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
    62 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
       
    63 import com.sun.tools.javac.code.Symbol.PackageSymbol;
       
    64 import com.sun.tools.javac.main.Option;
    63 
    65 
    64 /**
    66 /**
    65  * The FilerImplementation class must maintain a number of
    67  * The FilerImplementation class must maintain a number of
    66  * constraints.  First, multiple attempts to open the same path within
    68  * constraints.  First, multiple attempts to open the same path within
    67  * the same invocation of the tool results in an IOException being
    69  * the same invocation of the tool results in an IOException being
   382      */
   384      */
   383     private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames;
   385     private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames;
   384 
   386 
   385     private final Set<String> initialClassNames;
   387     private final Set<String> initialClassNames;
   386 
   388 
       
   389     private final String defaultTargetModule;
       
   390 
   387     JavacFiler(Context context) {
   391     JavacFiler(Context context) {
   388         this.context = context;
   392         this.context = context;
   389         fileManager = context.get(JavaFileManager.class);
   393         fileManager = context.get(JavaFileManager.class);
   390         elementUtils = JavacElements.instance(context);
   394         elementUtils = JavacElements.instance(context);
   391 
   395 
   406         aggregateGeneratedSourceNames = new LinkedHashSet<>();
   410         aggregateGeneratedSourceNames = new LinkedHashSet<>();
   407         aggregateGeneratedClassNames  = new LinkedHashSet<>();
   411         aggregateGeneratedClassNames  = new LinkedHashSet<>();
   408         initialClassNames  = new LinkedHashSet<>();
   412         initialClassNames  = new LinkedHashSet<>();
   409 
   413 
   410         lint = (Lint.instance(context)).isEnabled(PROCESSING);
   414         lint = (Lint.instance(context)).isEnabled(PROCESSING);
       
   415 
       
   416         Options options = Options.instance(context);
       
   417 
       
   418         defaultTargetModule = options.get(Option.DEFAULT_MODULE_FOR_CREATED_FILES);
   411     }
   419     }
   412 
   420 
   413     @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
   421     @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
   414     public JavaFileObject createSourceFile(CharSequence nameAndModule,
   422     public JavaFileObject createSourceFile(CharSequence nameAndModule,
   415                                            Element... originatingElements) throws IOException {
   423                                            Element... originatingElements) throws IOException {
   425     }
   433     }
   426 
   434 
   427     private Pair<ModuleSymbol, String> checkOrInferModule(CharSequence moduleAndPkg) throws FilerException {
   435     private Pair<ModuleSymbol, String> checkOrInferModule(CharSequence moduleAndPkg) throws FilerException {
   428         String moduleAndPkgString = moduleAndPkg.toString();
   436         String moduleAndPkgString = moduleAndPkg.toString();
   429         int slash = moduleAndPkgString.indexOf('/');
   437         int slash = moduleAndPkgString.indexOf('/');
   430 
   438         String module;
   431         if (slash != (-1)) {
   439         String pkg;
       
   440 
       
   441         if (slash == (-1)) {
       
   442             //module name not specified:
       
   443             int lastDot = moduleAndPkgString.lastIndexOf('.');
       
   444             String pack = lastDot != (-1) ? moduleAndPkgString.substring(0, lastDot) : "";
       
   445             ModuleSymbol msym = inferModule(pack);
       
   446 
       
   447             if (msym != null) {
       
   448                 return Pair.of(msym, moduleAndPkgString);
       
   449             }
       
   450 
       
   451             if (defaultTargetModule == null) {
       
   452                 throw new FilerException("Cannot determine target module.");
       
   453             }
       
   454 
       
   455             module = defaultTargetModule;
       
   456             pkg = moduleAndPkgString;
       
   457         } else {
   432             //module name specified:
   458             //module name specified:
   433             String module = moduleAndPkgString.substring(0, slash);
   459             module = moduleAndPkgString.substring(0, slash);
   434 
   460             pkg = moduleAndPkgString.substring(slash + 1);
   435             ModuleSymbol explicitModule = syms.getModule(names.fromString(module));
   461         }
   436 
   462 
   437             if (explicitModule == null) {
   463         ModuleSymbol explicitModule = syms.getModule(names.fromString(module));
   438                 throw new FilerException("Module: " + module + " does not exist.");
   464 
   439             }
   465         if (explicitModule == null) {
   440 
   466             throw new FilerException("Module: " + module + " does not exist.");
   441             if (!modules.isRootModule(explicitModule)) {
   467         }
   442                 throw new FilerException("Cannot write to the given module!");
   468 
   443             }
   469         if (!modules.isRootModule(explicitModule)) {
   444 
   470             throw new FilerException("Cannot write to the given module.");
   445             return Pair.of(explicitModule, moduleAndPkgString.substring(slash + 1));
   471         }
   446         } else {
   472 
   447             if (modules.multiModuleMode) {
   473         return Pair.of(explicitModule, pkg);
   448                 throw new FilerException("No module to write to specified!");
       
   449             }
       
   450 
       
   451             return Pair.of(modules.getDefaultModule(), moduleAndPkgString);
       
   452         }
       
   453     }
   474     }
   454 
   475 
   455     private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name) throws IOException {
   476     private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name) throws IOException {
   456         Assert.checkNonNull(mod);
   477         Assert.checkNonNull(mod);
   457 
   478 
   493     @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
   514     @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
   494     public FileObject createResource(JavaFileManager.Location location,
   515     public FileObject createResource(JavaFileManager.Location location,
   495                                      CharSequence moduleAndPkg,
   516                                      CharSequence moduleAndPkg,
   496                                      CharSequence relativeName,
   517                                      CharSequence relativeName,
   497                                      Element... originatingElements) throws IOException {
   518                                      Element... originatingElements) throws IOException {
   498         Pair<ModuleSymbol, String> moduleAndPackage = checkOrInferModule(moduleAndPkg);
   519         Tuple3<Location, ModuleSymbol, String> locationModuleAndPackage = checkOrInferModule(location, moduleAndPkg, true);
   499         ModuleSymbol msym = moduleAndPackage.fst;
   520         location = locationModuleAndPackage.a;
   500         String pkg = moduleAndPackage.snd;
   521         ModuleSymbol msym = locationModuleAndPackage.b;
       
   522         String pkg = locationModuleAndPackage.c;
   501 
   523 
   502         locationCheck(location);
   524         locationCheck(location);
   503 
       
   504         if (modules.multiModuleMode) {
       
   505             Assert.checkNonNull(msym);
       
   506             location = this.fileManager.getLocationForModule(location, msym.name.toString());
       
   507         }
       
   508 
   525 
   509         String strPkg = pkg.toString();
   526         String strPkg = pkg.toString();
   510         if (strPkg.length() > 0)
   527         if (strPkg.length() > 0)
   511             checkName(strPkg);
   528             checkName(strPkg);
   512 
   529 
   532 
   549 
   533     @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
   550     @Override @DefinedBy(Api.ANNOTATION_PROCESSING)
   534     public FileObject getResource(JavaFileManager.Location location,
   551     public FileObject getResource(JavaFileManager.Location location,
   535                                   CharSequence moduleAndPkg,
   552                                   CharSequence moduleAndPkg,
   536                                   CharSequence relativeName) throws IOException {
   553                                   CharSequence relativeName) throws IOException {
   537         Pair<ModuleSymbol, String> moduleAndPackage = checkOrInferModule(moduleAndPkg);
   554         Tuple3<Location, ModuleSymbol, String> locationModuleAndPackage = checkOrInferModule(location, moduleAndPkg, false);
   538         ModuleSymbol msym = moduleAndPackage.fst;
   555         location = locationModuleAndPackage.a;
   539         String pkg = moduleAndPackage.snd;
   556         String pkg = locationModuleAndPackage.c;
   540 
       
   541         if (modules.multiModuleMode) {
       
   542             Assert.checkNonNull(msym);
       
   543             location = this.fileManager.getLocationForModule(location, msym.name.toString());
       
   544         }
       
   545 
   557 
   546         if (pkg.length() > 0)
   558         if (pkg.length() > 0)
   547             checkName(pkg);
   559             checkName(pkg);
   548 
   560 
   549         // TODO: Only support reading resources in selected output
   561         // TODO: Only support reading resources in selected output
   574         }
   586         }
   575 
   587 
   576         // If the path was already opened for writing, throw an exception.
   588         // If the path was already opened for writing, throw an exception.
   577         checkFileReopening(fileObject, false);
   589         checkFileReopening(fileObject, false);
   578         return new FilerInputFileObject(fileObject);
   590         return new FilerInputFileObject(fileObject);
       
   591     }
       
   592 
       
   593     private Tuple3<JavaFileManager.Location, ModuleSymbol, String> checkOrInferModule(JavaFileManager.Location location,
       
   594                                                            CharSequence moduleAndPkg,
       
   595                                                            boolean write) throws IOException {
       
   596         String moduleAndPkgString = moduleAndPkg.toString();
       
   597         int slash = moduleAndPkgString.indexOf('/');
       
   598         boolean multiModuleLocation = location.isModuleOrientedLocation() ||
       
   599                                       (modules.multiModuleMode && location.isOutputLocation());
       
   600         String module;
       
   601         String pkg;
       
   602 
       
   603         if (slash == (-1)) {
       
   604             //module name not specified:
       
   605             if (!multiModuleLocation) {
       
   606                 //package oriented location:
       
   607                 return new Tuple3<>(location, modules.getDefaultModule(), moduleAndPkgString);
       
   608             }
       
   609 
       
   610             if (location.isOutputLocation()) {
       
   611                 ModuleSymbol msym = inferModule(moduleAndPkgString);
       
   612 
       
   613                 if (msym != null) {
       
   614                     Location moduleLoc =
       
   615                             fileManager.getLocationForModule(location, msym.name.toString());
       
   616                     return new Tuple3<>(moduleLoc, msym, moduleAndPkgString);
       
   617                 }
       
   618             }
       
   619 
       
   620             if (defaultTargetModule == null) {
       
   621                 throw new FilerException("No module specified and the location is either " +
       
   622                                          "a module-oriented location, or a multi-module " +
       
   623                                          "output location.");
       
   624             }
       
   625 
       
   626             module = defaultTargetModule;
       
   627             pkg = moduleAndPkgString;
       
   628         } else {
       
   629             //module name specified:
       
   630             module = moduleAndPkgString.substring(0, slash);
       
   631             pkg = moduleAndPkgString.substring(slash + 1);
       
   632         }
       
   633 
       
   634         if (multiModuleLocation) {
       
   635             ModuleSymbol explicitModule = syms.getModule(names.fromString(module));
       
   636 
       
   637             if (explicitModule == null) {
       
   638                 throw new FilerException("Module: " + module + " does not exist.");
       
   639             }
       
   640 
       
   641             if (write && !modules.isRootModule(explicitModule)) {
       
   642                 throw new FilerException("Cannot write to the given module.");
       
   643             }
       
   644 
       
   645             Location moduleLoc = fileManager.getLocationForModule(location, module);
       
   646 
       
   647             return new Tuple3<>(moduleLoc, explicitModule, pkg);
       
   648         } else {
       
   649             throw new FilerException("Module specified but the location is neither " +
       
   650                                      "a module-oriented location, nor a multi-module " +
       
   651                                      "output location.");
       
   652         }
       
   653     }
       
   654 
       
   655     static final class Tuple3<A, B, C> {
       
   656         final A a;
       
   657         final B b;
       
   658         final C c;
       
   659 
       
   660         public Tuple3(A a, B b, C c) {
       
   661             this.a = a;
       
   662             this.b = b;
       
   663             this.c = c;
       
   664         }
       
   665     }
       
   666 
       
   667     private ModuleSymbol inferModule(String pkg) {
       
   668         if (modules.getDefaultModule() == syms.noModule)
       
   669             return modules.getDefaultModule();
       
   670 
       
   671         Set<ModuleSymbol> rootModules = modules.getRootModules();
       
   672 
       
   673         if (rootModules.size() == 1) {
       
   674             return rootModules.iterator().next();
       
   675         }
       
   676 
       
   677         PackageSymbol pack = elementUtils.getPackageElement(pkg);
       
   678 
       
   679         if (pack != null && pack.modle != syms.unnamedModule) {
       
   680             return pack.modle;
       
   681         }
       
   682 
       
   683         return null;
   579     }
   684     }
   580 
   685 
   581     private void checkName(String name) throws FilerException {
   686     private void checkName(String name) throws FilerException {
   582         checkName(name, false);
   687         checkName(name, false);
   583     }
   688     }