StandardJavaFileManager.java revision 4010:a42d01aa6c9e
1177633Sdfr/* 2177633Sdfr * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. 3177633Sdfr * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4177633Sdfr * 5177633Sdfr * This code is free software; you can redistribute it and/or modify it 6177633Sdfr * under the terms of the GNU General Public License version 2 only, as 7177633Sdfr * published by the Free Software Foundation. Oracle designates this 8177633Sdfr * particular file as subject to the "Classpath" exception as provided 9177633Sdfr * by Oracle in the LICENSE file that accompanied this code. 10177633Sdfr * 11177633Sdfr * This code is distributed in the hope that it will be useful, but WITHOUT 12177633Sdfr * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13177633Sdfr * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14177633Sdfr * version 2 for more details (a copy is included in the LICENSE file that 15177633Sdfr * accompanied this code). 16177633Sdfr * 17177633Sdfr * You should have received a copy of the GNU General Public License version 18177633Sdfr * 2 along with this work; if not, write to the Free Software Foundation, 19177633Sdfr * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20177633Sdfr * 21177633Sdfr * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22177633Sdfr * or visit www.oracle.com if you need additional information or have any 23177633Sdfr * questions. 24177633Sdfr */ 25177633Sdfr 26177633Sdfrpackage javax.tools; 27177633Sdfr 28177633Sdfrimport java.io.File; 29177633Sdfrimport java.io.IOException; 30177633Sdfrimport java.nio.file.Path; 31177633Sdfrimport java.util.Arrays; 32177633Sdfrimport java.util.Collection; 33177633Sdfr 34177633Sdfrimport static javax.tools.FileManagerUtils.*; 35177633Sdfr 36177633Sdfr/** 37177633Sdfr * File manager based on {@linkplain File java.io.File} and {@linkplain Path java.nio.file.Path}. 38177633Sdfr * 39180025Sdfr * A common way to obtain an instance of this class is using 40180025Sdfr * {@linkplain JavaCompiler#getStandardFileManager getStandardFileManager}, for example: 41180025Sdfr * 42180025Sdfr * <pre> 43180025Sdfr * JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 44180025Sdfr * {@code DiagnosticCollector<JavaFileObject>} diagnostics = 45177633Sdfr * new {@code DiagnosticCollector<JavaFileObject>()}; 46180025Sdfr * StandardJavaFileManager fm = compiler.getStandardFileManager(diagnostics, null, null); 47177633Sdfr * </pre> 48180025Sdfr * 49180025Sdfr * This file manager creates file objects representing regular 50180025Sdfr * {@linkplain File files}, 51177633Sdfr * {@linkplain java.util.zip.ZipEntry zip file entries}, or entries in 52177633Sdfr * similar file system based containers. Any file object returned 53177633Sdfr * from a file manager implementing this interface must observe the 54177633Sdfr * following behavior: 55177633Sdfr * 56177633Sdfr * <ul> 57177633Sdfr * <li> 58177633Sdfr * File names need not be canonical. 59177633Sdfr * </li> 60180025Sdfr * <li> 61177633Sdfr * For file objects representing regular files 62180025Sdfr * <ul> 63180025Sdfr * <li> 64180025Sdfr * the method <code>{@linkplain FileObject#delete()}</code> 65180025Sdfr * is equivalent to <code>{@linkplain File#delete()}</code>, 66177633Sdfr * </li> 67177633Sdfr * <li> 68180025Sdfr * the method <code>{@linkplain FileObject#getLastModified()}</code> 69177633Sdfr * is equivalent to <code>{@linkplain File#lastModified()}</code>, 70177633Sdfr * </li> 71177633Sdfr * <li> 72177633Sdfr * the methods <code>{@linkplain FileObject#getCharContent(boolean)}</code>, 73177633Sdfr * <code>{@linkplain FileObject#openInputStream()}</code>, and 74180025Sdfr * <code>{@linkplain FileObject#openReader(boolean)}</code> 75180025Sdfr * must succeed if the following would succeed (ignoring 76177633Sdfr * encoding issues): 77177633Sdfr * <blockquote> 78177633Sdfr * <pre>new {@linkplain java.io.FileInputStream#FileInputStream(File) FileInputStream}(new {@linkplain File#File(java.net.URI) File}({@linkplain FileObject fileObject}.{@linkplain FileObject#toUri() toUri}()))</pre> 79177633Sdfr * </blockquote> 80177633Sdfr * </li> 81180025Sdfr * <li> 82180025Sdfr * and the methods 83180025Sdfr * <code>{@linkplain FileObject#openOutputStream()}</code>, and 84180025Sdfr * <code>{@linkplain FileObject#openWriter()}</code> must 85180025Sdfr * succeed if the following would succeed (ignoring encoding 86180025Sdfr * issues): 87180025Sdfr * <blockquote> 88180025Sdfr * <pre>new {@linkplain java.io.FileOutputStream#FileOutputStream(File) FileOutputStream}(new {@linkplain File#File(java.net.URI) File}({@linkplain FileObject fileObject}.{@linkplain FileObject#toUri() toUri}()))</pre> 89180025Sdfr * </blockquote> 90180025Sdfr * </li> 91180025Sdfr * </ul> 92180025Sdfr * </li> 93177633Sdfr * <li> 94177633Sdfr * The {@linkplain java.net.URI URI} returned from 95177633Sdfr * <code>{@linkplain FileObject#toUri()}</code> 96184588Sdfr * <ul> 97177633Sdfr * <li> 98177633Sdfr * must be {@linkplain java.net.URI#isAbsolute() absolute} (have a schema), and 99180025Sdfr * </li> 100180025Sdfr * <li> 101180025Sdfr * must have a {@linkplain java.net.URI#normalize() normalized} 102180025Sdfr * {@linkplain java.net.URI#getPath() path component} which 103180025Sdfr * can be resolved without any process-specific context such 104180025Sdfr * as the current directory (file names must be absolute). 105180025Sdfr * </li> 106180025Sdfr * </ul> 107180025Sdfr * </li> 108180025Sdfr * </ul> 109180025Sdfr * 110180025Sdfr * According to these rules, the following URIs, for example, are 111180025Sdfr * allowed: 112180025Sdfr * <ul> 113180025Sdfr * <li> 114180025Sdfr * <code>file:///C:/Documents%20and%20Settings/UncleBob/BobsApp/Test.java</code> 115180025Sdfr * </li> 116180025Sdfr * <li> 117180025Sdfr * <code>jar:///C:/Documents%20and%20Settings/UncleBob/lib/vendorA.jar!/com/vendora/LibraryClass.class</code> 118180025Sdfr * </li> 119180025Sdfr * </ul> 120180025Sdfr * Whereas these are not (reason in parentheses): 121180025Sdfr * <ul> 122180025Sdfr * <li> 123180025Sdfr * <code>file:BobsApp/Test.java</code> (the file name is relative 124180025Sdfr * and depend on the current directory) 125180025Sdfr * </li> 126180025Sdfr * <li> 127180025Sdfr * <code>jar:lib/vendorA.jar!/com/vendora/LibraryClass.class</code> 128180025Sdfr * (the first half of the path depends on the current directory, 129180025Sdfr * whereas the component after ! is legal) 130180025Sdfr * </li> 131180025Sdfr * <li> 132180025Sdfr * <code>Test.java</code> (this URI depends on the current 133180025Sdfr * directory and does not have a schema) 134180025Sdfr * </li> 135180025Sdfr * <li> 136180025Sdfr * <code>jar:///C:/Documents%20and%20Settings/UncleBob/BobsApp/../lib/vendorA.jar!com/vendora/LibraryClass.class</code> 137180025Sdfr * (the path is not normalized) 138180025Sdfr * </li> 139180025Sdfr * </ul> 140180025Sdfr * 141177633Sdfr * <p>All implementations of this interface must support Path objects representing 142177633Sdfr * files in the {@linkplain java.nio.file.FileSystems#getDefault() default file system.} 143177633Sdfr * It is recommended that implementations should support Path objects from any filesystem.</p> 144177633Sdfr * 145177633Sdfr * 146180025Sdfr * @apiNote 147180025Sdfr * Some methods on this interface take a {@code Collection<? extends Path>} 148180025Sdfr * instead of {@code Iterable<? extends Path>}. 149180025Sdfr * This is to prevent the possibility of accidentally calling the method 150180025Sdfr * with a single {@code Path} as such an argument, because although 151177633Sdfr * {@code Path} implements {@code Iterable<Path>}, it would almost never be 152180025Sdfr * correct to call these methods with a single {@code Path} and have it be treated as 153180025Sdfr * an {@code Iterable} of its components. 154177633Sdfr * 155177633Sdfr * 156180025Sdfr * @author Peter von der Ahé 157180025Sdfr * @since 1.6 158180025Sdfr */ 159180025Sdfrpublic interface StandardJavaFileManager extends JavaFileManager { 160180025Sdfr 161177633Sdfr /** 162180025Sdfr * Compares two file objects and return true if they represent the 163180025Sdfr * same canonical file, zip file entry, or entry in any file 164177633Sdfr * system based container. 165177633Sdfr * 166180025Sdfr * @param a a file object 167180025Sdfr * @param b a file object 168180025Sdfr * @return true if the given file objects represent the same 169180025Sdfr * canonical file, zip file entry or path; false otherwise 170180025Sdfr * 171177633Sdfr * @throws IllegalArgumentException if either of the arguments 172180025Sdfr * were created with another file manager implementation 173180025Sdfr */ 174177633Sdfr @Override 175177633Sdfr boolean isSameFile(FileObject a, FileObject b); 176180025Sdfr 177180025Sdfr /** 178180025Sdfr * Returns file objects representing the given files. 179180025Sdfr * 180180025Sdfr * @param files a list of files 181177633Sdfr * @return a list of file objects 182180025Sdfr * @throws IllegalArgumentException if the list of files includes 183180025Sdfr * a directory 184177633Sdfr */ 185177633Sdfr Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles( 186180025Sdfr Iterable<? extends File> files); 187180025Sdfr 188180025Sdfr /** 189180025Sdfr * Returns file objects representing the given paths. 190180025Sdfr * 191180025Sdfr * @implSpec 192180025Sdfr * The default implementation converts each path to a file and calls 193180025Sdfr * {@link #getJavaFileObjectsFromFiles getJavaObjectsFromFiles}. 194180025Sdfr * IllegalArgumentException will be thrown if any of the paths 195180025Sdfr * cannot be converted to a file. 196177633Sdfr * 197177633Sdfr * @param paths a list of paths 198177633Sdfr * @return a list of file objects 199177633Sdfr * @throws IllegalArgumentException if the list of paths includes 200177633Sdfr * a directory or if this file manager does not support any of the 201180025Sdfr * given paths. 202177633Sdfr * 203180025Sdfr * @since 9 204177633Sdfr */ 205180025Sdfr default Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths( 206180025Sdfr Iterable<? extends Path> paths) { 207180025Sdfr return getJavaFileObjectsFromFiles(asFiles(paths)); 208180025Sdfr } 209180025Sdfr 210180025Sdfr /** 211180025Sdfr * Returns file objects representing the given files. 212180025Sdfr * Convenience method equivalent to: 213177633Sdfr * 214177633Sdfr * <pre> 215177633Sdfr * getJavaFileObjectsFromFiles({@linkplain java.util.Arrays#asList Arrays.asList}(files)) 216 * </pre> 217 * 218 * @param files an array of files 219 * @return a list of file objects 220 * @throws IllegalArgumentException if the array of files includes 221 * a directory 222 * @throws NullPointerException if the given array contains null 223 * elements 224 */ 225 Iterable<? extends JavaFileObject> getJavaFileObjects(File... files); 226 227 /** 228 * Returns file objects representing the given paths. 229 * Convenience method equivalent to: 230 * 231 * <pre> 232 * getJavaFileObjectsFromPaths({@linkplain java.util.Arrays#asList Arrays.asList}(paths)) 233 * </pre> 234 * 235 * @param paths an array of paths 236 * @return a list of file objects 237 * @throws IllegalArgumentException if the array of files includes 238 * a directory 239 * @throws NullPointerException if the given array contains null 240 * elements 241 * 242 * @since 9 243 */ 244 default Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) { 245 return getJavaFileObjectsFromPaths(Arrays.asList(paths)); 246 } 247 248 /** 249 * Returns file objects representing the given file names. 250 * 251 * @param names a list of file names 252 * @return a list of file objects 253 * @throws IllegalArgumentException if the list of file names 254 * includes a directory 255 */ 256 Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings( 257 Iterable<String> names); 258 259 /** 260 * Returns file objects representing the given file names. 261 * Convenience method equivalent to: 262 * 263 * <pre> 264 * getJavaFileObjectsFromStrings({@linkplain java.util.Arrays#asList Arrays.asList}(names)) 265 * </pre> 266 * 267 * @param names a list of file names 268 * @return a list of file objects 269 * @throws IllegalArgumentException if the array of file names 270 * includes a directory 271 * @throws NullPointerException if the given array contains null 272 * elements 273 */ 274 Iterable<? extends JavaFileObject> getJavaFileObjects(String... names); 275 276 /** 277 * Associates the given search path with the given location. Any 278 * previous value will be discarded. 279 * 280 * If the location is a module-oriented or output location, any module-specific 281 * associations set up by {@linkplain #setLocationForModule setLocationForModule} 282 * will be cancelled. 283 * 284 * @param location a location 285 * @param files a list of files, if {@code null} use the default 286 * search path for this location 287 * @see #getLocation 288 * @throws IllegalArgumentException if {@code location} is an output 289 * location and {@code files} does not contain exactly one element 290 * @throws IOException if {@code location} is an output location and 291 * does not represent an existing directory 292 */ 293 void setLocation(Location location, Iterable<? extends File> files) 294 throws IOException; 295 296 /** 297 * Associates the given search path with the given location. 298 * Any previous value will be discarded. 299 * 300 * If the location is a module-oriented or output location, any module-specific 301 * associations set up by {@linkplain #setLocationForModule setLocationForModule} 302 * will be cancelled. 303 * 304 * @implSpec 305 * The default implementation converts each path to a file and calls 306 * {@link #getJavaFileObjectsFromFiles getJavaObjectsFromFiles}. 307 * {@linkplain IllegalArgumentException IllegalArgumentException} 308 * will be thrown if any of the paths cannot be converted to a file. 309 * 310 * @param location a location 311 * @param paths a list of paths, if {@code null} use the default 312 * search path for this location 313 * @see #getLocation 314 * @throws IllegalArgumentException if {@code location} is an output 315 * location and {@code paths} does not contain exactly one element 316 * or if this file manager does not support any of the given paths 317 * @throws IOException if {@code location} is an output location and 318 * {@code paths} does not represent an existing directory 319 * 320 * @since 9 321 */ 322 default void setLocationFromPaths(Location location, Collection<? extends Path> paths) 323 throws IOException { 324 setLocation(location, asFiles(paths)); 325 } 326 327 /** 328 * Associates the given search path with the given module and location, 329 * which must be a module-oriented or output location. 330 * Any previous value will be discarded. 331 * This overrides any default association derived from the search path 332 * associated with the location itself. 333 * 334 * All such module-specific associations will be cancelled if a 335 * new search path is associated with the location by calling 336 * {@linkplain #setLocation setLocation } or 337 * {@linkplain #setLocationFromPaths setLocationFromPaths}. 338 * 339 * @throws IllegalStateException if the location is not a module-oriented 340 * or output location. 341 * @throws UnsupportedOperationException if this operation is not supported by 342 * this file manager. 343 * @throws IOException if {@code location} is an output location and 344 * {@code paths} does not represent an existing directory 345 * 346 * @param location the location 347 * @param moduleName the name of the module 348 * @param paths the search path to associate with the location and module. 349 * 350 * @see setLocation 351 * @see setLocationFromPaths 352 */ 353 default void setLocationForModule(Location location, String moduleName, 354 Collection<? extends Path> paths) throws IOException { 355 throw new UnsupportedOperationException(); 356 } 357 358 /** 359 * Returns the search path associated with the given location. 360 * 361 * @param location a location 362 * @return a list of files or {@code null} if this location has no 363 * associated search path 364 * @throws IllegalStateException if any element of the search path 365 * cannot be converted to a {@linkplain File}. 366 * 367 * @see #setLocation 368 * @see Path#toFile 369 */ 370 Iterable<? extends File> getLocation(Location location); 371 372 /** 373 * Returns the search path associated with the given location. 374 * 375 * @implSpec 376 * The default implementation calls {@link #getLocation getLocation} 377 * and then returns an {@code Iterable} formed by calling {@code toPath()} 378 * on each {@code File} returned from {@code getLocation}. 379 * 380 * @param location a location 381 * @return a list of paths or {@code null} if this location has no 382 * associated search path 383 * 384 * @see #setLocationFromPaths 385 * @since 9 386 */ 387 default Iterable<? extends Path> getLocationAsPaths(Location location) { 388 return asPaths(getLocation(location)); 389 } 390 391 /** 392 * Returns the path, if any, underlying this file object (optional operation). 393 * File objects derived from a {@link java.nio.file.FileSystem FileSystem}, 394 * including the default file system, typically have a corresponding underlying 395 * {@link java.nio.file.Path Path} object. In such cases, this method may be 396 * used to access that object. 397 * 398 * @implSpec 399 * The default implementation throws {@link UnsupportedOperationException} 400 * for all files. 401 * 402 * @param file a file object 403 * @return a path representing the same underlying file system artifact 404 * @throws IllegalArgumentException if the file object does not have an underlying path 405 * @throws UnsupportedOperationException if the operation is not supported by this file manager 406 * 407 * @since 9 408 */ 409 default Path asPath(FileObject file) { 410 throw new UnsupportedOperationException(); 411 } 412 413 /** 414 * Factory to create {@code Path} objects from strings. 415 * 416 * @since 9 417 */ 418 interface PathFactory { 419 /** 420 * Converts a path string, or a sequence of strings that when joined form a path string, to a Path. 421 * 422 * @param first the path string or initial part of the path string 423 * @param more additional strings to be joined to form the path string 424 * @return the resulting {@code Path} 425 */ 426 Path getPath(String first, String... more); 427 } 428 429 /** 430 * Specify a factory that can be used to generate a path from a string, or series of strings. 431 * 432 * If this method is not called, a factory whose {@code getPath} method is 433 * equivalent to calling 434 * {@link java.nio.file.Paths#get(String, String...) java.nio.file.Paths.get(first, more)} 435 * will be used. 436 * 437 * @implSpec 438 * The default implementation of this method ignores the factory that is provided. 439 * 440 * @param f the factory 441 * 442 * @since 9 443 */ 444 default void setPathFactory(PathFactory f) { } 445} 446