|
1 /* |
|
2 * Copyright (c) 2014, 2015, 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 jdk.jshell; |
|
27 |
|
28 import java.io.ByteArrayInputStream; |
|
29 import java.io.ByteArrayOutputStream; |
|
30 import java.io.IOException; |
|
31 import java.io.InputStream; |
|
32 import java.io.OutputStream; |
|
33 import java.lang.reflect.InvocationTargetException; |
|
34 import java.lang.reflect.Method; |
|
35 import java.net.URI; |
|
36 import java.nio.file.FileSystems; |
|
37 import java.nio.file.Files; |
|
38 import java.nio.file.Path; |
|
39 import java.util.Collection; |
|
40 import java.util.Iterator; |
|
41 import java.util.Map; |
|
42 import java.util.NoSuchElementException; |
|
43 import java.util.Set; |
|
44 import java.util.TreeMap; |
|
45 import javax.tools.JavaFileObject.Kind; |
|
46 import static javax.tools.StandardLocation.CLASS_PATH; |
|
47 import javax.tools.FileObject; |
|
48 import javax.tools.JavaFileManager; |
|
49 import javax.tools.JavaFileObject; |
|
50 import javax.tools.SimpleJavaFileObject; |
|
51 import javax.tools.StandardJavaFileManager; |
|
52 |
|
53 import com.sun.tools.javac.util.DefinedBy; |
|
54 import com.sun.tools.javac.util.DefinedBy.Api; |
|
55 |
|
56 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_FMGR; |
|
57 |
|
58 /** |
|
59 * File manager for the compiler API. Reads from memory (Strings) and writes |
|
60 * class files to memory (cached OutputMemoryJavaFileObject). |
|
61 * |
|
62 * @author Robert Field |
|
63 */ |
|
64 class MemoryFileManager implements JavaFileManager { |
|
65 |
|
66 private final StandardJavaFileManager stdFileManager; |
|
67 |
|
68 private final Map<String, OutputMemoryJavaFileObject> classObjects = new TreeMap<>(); |
|
69 |
|
70 private ClassFileCreationListener classListener = null; |
|
71 |
|
72 private final ClassLoader loader = new REPLClassLoader(); |
|
73 |
|
74 private final JShell proc; |
|
75 |
|
76 // Upcoming Jigsaw |
|
77 private Method inferModuleNameMethod = null; |
|
78 private Method listModuleLocationsMethod = null; |
|
79 |
|
80 static abstract class MemoryJavaFileObject extends SimpleJavaFileObject { |
|
81 |
|
82 public MemoryJavaFileObject(String name, JavaFileObject.Kind kind) { |
|
83 super(URI.create("string:///" + name.replace('.', '/') |
|
84 + kind.extension), kind); |
|
85 } |
|
86 } |
|
87 |
|
88 class SourceMemoryJavaFileObject extends MemoryJavaFileObject { |
|
89 private final String src; |
|
90 private final Object origin; |
|
91 |
|
92 SourceMemoryJavaFileObject(Object origin, String className, String code) { |
|
93 super(className, JavaFileObject.Kind.SOURCE); |
|
94 this.origin = origin; |
|
95 this.src = code; |
|
96 } |
|
97 |
|
98 public Object getOrigin() { |
|
99 return origin; |
|
100 } |
|
101 |
|
102 @Override @DefinedBy(Api.COMPILER) |
|
103 public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
|
104 return src; |
|
105 } |
|
106 } |
|
107 |
|
108 static class OutputMemoryJavaFileObject extends MemoryJavaFileObject { |
|
109 |
|
110 /** |
|
111 * Byte code created by the compiler will be stored in this |
|
112 * ByteArrayOutputStream. |
|
113 */ |
|
114 private ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
|
115 private byte[] bytes = null; |
|
116 |
|
117 private final String className; |
|
118 |
|
119 public OutputMemoryJavaFileObject(String name, JavaFileObject.Kind kind) { |
|
120 super(name, kind); |
|
121 this.className = name; |
|
122 } |
|
123 |
|
124 public byte[] getBytes() { |
|
125 if (bytes == null) { |
|
126 bytes = bos.toByteArray(); |
|
127 bos = null; |
|
128 } |
|
129 return bytes; |
|
130 } |
|
131 |
|
132 public void dump() { |
|
133 try { |
|
134 Path dumpDir = FileSystems.getDefault().getPath("dump"); |
|
135 if (Files.notExists(dumpDir)) { |
|
136 Files.createDirectory(dumpDir); |
|
137 } |
|
138 Path file = FileSystems.getDefault().getPath("dump", getName() + ".class"); |
|
139 Files.write(file, getBytes()); |
|
140 } catch (IOException ex) { |
|
141 throw new RuntimeException(ex); |
|
142 } |
|
143 } |
|
144 |
|
145 @Override @DefinedBy(Api.COMPILER) |
|
146 public String getName() { |
|
147 return className; |
|
148 } |
|
149 |
|
150 /** |
|
151 * Will provide the compiler with an output stream that leads to our |
|
152 * byte array. |
|
153 */ |
|
154 @Override @DefinedBy(Api.COMPILER) |
|
155 public OutputStream openOutputStream() throws IOException { |
|
156 return bos; |
|
157 } |
|
158 |
|
159 @Override @DefinedBy(Api.COMPILER) |
|
160 public InputStream openInputStream() throws IOException { |
|
161 return new ByteArrayInputStream(getBytes()); |
|
162 } |
|
163 } |
|
164 |
|
165 // For restoring process-local execution support |
|
166 class REPLClassLoader extends ClassLoader { |
|
167 |
|
168 @Override |
|
169 protected Class<?> findClass(String name) throws ClassNotFoundException { |
|
170 OutputMemoryJavaFileObject fo = classObjects.get(name); |
|
171 proc.debug(DBG_FMGR, "findClass %s = %s\n", name, fo); |
|
172 if (fo == null) { |
|
173 throw new ClassNotFoundException("Not ours"); |
|
174 } |
|
175 byte[] b = fo.getBytes(); |
|
176 return super.defineClass(name, b, 0, b.length, null); |
|
177 } |
|
178 } |
|
179 |
|
180 public MemoryFileManager(StandardJavaFileManager standardManager, JShell proc) { |
|
181 this.stdFileManager = standardManager; |
|
182 this.proc = proc; |
|
183 } |
|
184 |
|
185 private Collection<OutputMemoryJavaFileObject> generatedClasses() { |
|
186 return classObjects.values(); |
|
187 } |
|
188 |
|
189 // For debugging dumps |
|
190 public void dumpClasses() { |
|
191 for (OutputMemoryJavaFileObject co : generatedClasses()) { |
|
192 co.dump(); |
|
193 } |
|
194 } |
|
195 |
|
196 // For restoring process-local execution support |
|
197 public Class<?> findGeneratedClass(String genClassFullName) throws ClassNotFoundException { |
|
198 for (OutputMemoryJavaFileObject co : generatedClasses()) { |
|
199 if (co.className.equals(genClassFullName)) { |
|
200 Class<?> klass = loadClass(co.className); |
|
201 proc.debug(DBG_FMGR, "Loaded %s\n", klass); |
|
202 return klass; |
|
203 } |
|
204 } |
|
205 return null; |
|
206 } |
|
207 |
|
208 // For restoring process-local execution support |
|
209 public byte[] findGeneratedBytes(String genClassFullName) throws ClassNotFoundException { |
|
210 for (OutputMemoryJavaFileObject co : generatedClasses()) { |
|
211 if (co.className.equals(genClassFullName)) { |
|
212 return co.getBytes(); |
|
213 } |
|
214 } |
|
215 return null; |
|
216 } |
|
217 |
|
218 // For restoring process-local execution support |
|
219 public Class<?> loadClass(String name) throws ClassNotFoundException { |
|
220 return getClassLoader(null).loadClass(name); |
|
221 } |
|
222 |
|
223 public JavaFileObject createSourceFileObject(Object origin, String name, String code) { |
|
224 return new SourceMemoryJavaFileObject(origin, name, code); |
|
225 } |
|
226 |
|
227 // Make compatible with Jigsaw |
|
228 public String inferModuleName(Location location) { |
|
229 try { |
|
230 if (inferModuleNameMethod == null) { |
|
231 inferModuleNameMethod = JavaFileManager.class.getDeclaredMethod("inferModuleName", Location.class); |
|
232 } |
|
233 @SuppressWarnings("unchecked") |
|
234 String result = (String) inferModuleNameMethod.invoke(stdFileManager, location); |
|
235 return result; |
|
236 } catch (NoSuchMethodException | SecurityException ex) { |
|
237 throw new InternalError("Cannot lookup JavaFileManager method", ex); |
|
238 } catch (IllegalAccessException | |
|
239 IllegalArgumentException | |
|
240 InvocationTargetException ex) { |
|
241 throw new InternalError("Cannot invoke JavaFileManager method", ex); |
|
242 } |
|
243 } |
|
244 |
|
245 // Make compatible with Jigsaw |
|
246 public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException { |
|
247 try { |
|
248 if (listModuleLocationsMethod == null) { |
|
249 listModuleLocationsMethod = JavaFileManager.class.getDeclaredMethod("listModuleLocations", Location.class); |
|
250 } |
|
251 @SuppressWarnings("unchecked") |
|
252 Iterable<Set<Location>> result = (Iterable<Set<Location>>) listModuleLocationsMethod.invoke(stdFileManager, location); |
|
253 return result; |
|
254 } catch (NoSuchMethodException | SecurityException ex) { |
|
255 throw new InternalError("Cannot lookup JavaFileManager method", ex); |
|
256 } catch (IllegalAccessException | |
|
257 IllegalArgumentException | |
|
258 InvocationTargetException ex) { |
|
259 throw new InternalError("Cannot invoke JavaFileManager method", ex); |
|
260 } |
|
261 } |
|
262 |
|
263 |
|
264 /** |
|
265 * Returns a class loader for loading plug-ins from the given location. For |
|
266 * example, to load annotation processors, a compiler will request a class |
|
267 * loader for the {@link |
|
268 * StandardLocation#ANNOTATION_PROCESSOR_PATH |
|
269 * ANNOTATION_PROCESSOR_PATH} location. |
|
270 * |
|
271 * @param location a location |
|
272 * @return a class loader for the given location; or {@code null} |
|
273 * if loading plug-ins from the given location is disabled or if |
|
274 * the location is not known |
|
275 * @throws SecurityException if a class loader can not be created |
|
276 * in the current security context |
|
277 * @throws IllegalStateException if {@link #close} has been called |
|
278 * and this file manager cannot be reopened |
|
279 */ |
|
280 @Override @DefinedBy(Api.COMPILER) |
|
281 public ClassLoader getClassLoader(JavaFileManager.Location location) { |
|
282 proc.debug(DBG_FMGR, "getClassLoader: location\n", location); |
|
283 return loader; |
|
284 } |
|
285 |
|
286 /** |
|
287 * Lists all file objects matching the given criteria in the given |
|
288 * location. List file objects in "subpackages" if recurse is |
|
289 * true. |
|
290 * |
|
291 * <p>Note: even if the given location is unknown to this file |
|
292 * manager, it may not return {@code null}. Also, an unknown |
|
293 * location may not cause an exception. |
|
294 * |
|
295 * @param location a location |
|
296 * @param packageName a package name |
|
297 * @param kinds return objects only of these kinds |
|
298 * @param recurse if true include "subpackages" |
|
299 * @return an Iterable of file objects matching the given criteria |
|
300 * @throws IOException if an I/O error occurred, or if {@link |
|
301 * #close} has been called and this file manager cannot be |
|
302 * reopened |
|
303 * @throws IllegalStateException if {@link #close} has been called |
|
304 * and this file manager cannot be reopened |
|
305 */ |
|
306 @Override @DefinedBy(Api.COMPILER) |
|
307 public Iterable<JavaFileObject> list(JavaFileManager.Location location, |
|
308 String packageName, |
|
309 Set<JavaFileObject.Kind> kinds, |
|
310 boolean recurse) |
|
311 throws IOException { |
|
312 Iterable<JavaFileObject> stdList = stdFileManager.list(location, packageName, kinds, recurse); |
|
313 if (location==CLASS_PATH && packageName.equals("REPL")) { |
|
314 // if the desired list is for our JShell package, lazily iterate over |
|
315 // first the standard list then any generated classes. |
|
316 return () -> new Iterator<JavaFileObject>() { |
|
317 boolean stdDone = false; |
|
318 Iterator<? extends JavaFileObject> it; |
|
319 |
|
320 @Override |
|
321 public boolean hasNext() { |
|
322 if (it == null) { |
|
323 it = stdList.iterator(); |
|
324 } |
|
325 if (it.hasNext()) { |
|
326 return true; |
|
327 } |
|
328 if (stdDone) { |
|
329 return false; |
|
330 } else { |
|
331 stdDone = true; |
|
332 it = generatedClasses().iterator(); |
|
333 return it.hasNext(); |
|
334 } |
|
335 } |
|
336 |
|
337 @Override |
|
338 public JavaFileObject next() { |
|
339 if (!hasNext()) { |
|
340 throw new NoSuchElementException(); |
|
341 } |
|
342 return it.next(); |
|
343 } |
|
344 |
|
345 }; |
|
346 } else { |
|
347 return stdList; |
|
348 } |
|
349 } |
|
350 |
|
351 /** |
|
352 * Infers a binary name of a file object based on a location. The |
|
353 * binary name returned might not be a valid binary name according to |
|
354 * <cite>The Java&trade { throw new UnsupportedOperationException("Not supported yet."); } Language Specification</cite>. |
|
355 * |
|
356 * @param location a location |
|
357 * @param file a file object |
|
358 * @return a binary name or {@code null} the file object is not |
|
359 * found in the given location |
|
360 * @throws IllegalStateException if {@link #close} has been called |
|
361 * and this file manager cannot be reopened |
|
362 */ |
|
363 @Override @DefinedBy(Api.COMPILER) |
|
364 public String inferBinaryName(JavaFileManager.Location location, JavaFileObject file) { |
|
365 if (file instanceof OutputMemoryJavaFileObject) { |
|
366 OutputMemoryJavaFileObject ofo = (OutputMemoryJavaFileObject) file; |
|
367 proc.debug(DBG_FMGR, "inferBinaryName %s => %s\n", file, ofo.getName()); |
|
368 return ofo.getName(); |
|
369 } else { |
|
370 return stdFileManager.inferBinaryName(location, file); |
|
371 } |
|
372 } |
|
373 |
|
374 /** |
|
375 * Compares two file objects and return true if they represent the |
|
376 * same underlying object. |
|
377 * |
|
378 * @param a a file object |
|
379 * @param b a file object |
|
380 * @return true if the given file objects represent the same |
|
381 * underlying object |
|
382 * |
|
383 * @throws IllegalArgumentException if either of the arguments |
|
384 * were created with another file manager and this file manager |
|
385 * does not support foreign file objects |
|
386 */ |
|
387 @Override @DefinedBy(Api.COMPILER) |
|
388 public boolean isSameFile(FileObject a, FileObject b) { |
|
389 return stdFileManager.isSameFile(b, b); |
|
390 } |
|
391 |
|
392 /** |
|
393 * Determines if the given option is supported and if so, the |
|
394 * number of arguments the option takes. |
|
395 * |
|
396 * @param option an option |
|
397 * @return the number of arguments the given option takes or -1 if |
|
398 * the option is not supported |
|
399 */ |
|
400 @Override @DefinedBy(Api.COMPILER) |
|
401 public int isSupportedOption(String option) { |
|
402 proc.debug(DBG_FMGR, "isSupportedOption: %s\n", option); |
|
403 return stdFileManager.isSupportedOption(option); |
|
404 } |
|
405 |
|
406 /** |
|
407 * Handles one option. If {@code current} is an option to this |
|
408 * file manager it will consume any arguments to that option from |
|
409 * {@code remaining} and return true, otherwise return false. |
|
410 * |
|
411 * @param current current option |
|
412 * @param remaining remaining options |
|
413 * @return true if this option was handled by this file manager, |
|
414 * false otherwise |
|
415 * @throws IllegalArgumentException if this option to this file |
|
416 * manager is used incorrectly |
|
417 * @throws IllegalStateException if {@link #close} has been called |
|
418 * and this file manager cannot be reopened |
|
419 */ |
|
420 @Override @DefinedBy(Api.COMPILER) |
|
421 public boolean handleOption(String current, Iterator<String> remaining) { |
|
422 proc.debug(DBG_FMGR, "handleOption: current: %s\n", current + |
|
423 ", remaining: " + remaining); |
|
424 return stdFileManager.handleOption(current, remaining); |
|
425 } |
|
426 |
|
427 /** |
|
428 * Determines if a location is known to this file manager. |
|
429 * |
|
430 * @param location a location |
|
431 * @return true if the location is known |
|
432 */ |
|
433 @Override @DefinedBy(Api.COMPILER) |
|
434 public boolean hasLocation(JavaFileManager.Location location) { |
|
435 proc.debug(DBG_FMGR, "hasLocation: location: %s\n", location); |
|
436 return stdFileManager.hasLocation(location); |
|
437 } |
|
438 |
|
439 interface ClassFileCreationListener { |
|
440 void newClassFile(OutputMemoryJavaFileObject jfo, JavaFileManager.Location location, |
|
441 String className, Kind kind, FileObject sibling); |
|
442 } |
|
443 |
|
444 void registerClassFileCreationListener(ClassFileCreationListener listen) { |
|
445 this.classListener = listen; |
|
446 } |
|
447 |
|
448 /** |
|
449 * Returns a {@linkplain JavaFileObject file object} for input |
|
450 * representing the specified class of the specified kind in the |
|
451 * given location. |
|
452 * |
|
453 * @param location a location |
|
454 * @param className the name of a class |
|
455 * @param kind the kind of file, must be one of {@link |
|
456 * JavaFileObject.Kind#SOURCE SOURCE} or {@link |
|
457 * JavaFileObject.Kind#CLASS CLASS} |
|
458 * @return a file object, might return {@code null} if the |
|
459 * file does not exist |
|
460 * @throws IllegalArgumentException if the location is not known |
|
461 * to this file manager and the file manager does not support |
|
462 * unknown locations, or if the kind is not valid |
|
463 * @throws IOException if an I/O error occurred, or if {@link |
|
464 * #close} has been called and this file manager cannot be |
|
465 * reopened |
|
466 * @throws IllegalStateException if {@link #close} has been called |
|
467 * and this file manager cannot be reopened |
|
468 */ |
|
469 @Override @DefinedBy(Api.COMPILER) |
|
470 public JavaFileObject getJavaFileForInput(JavaFileManager.Location location, |
|
471 String className, |
|
472 JavaFileObject.Kind kind) |
|
473 throws IOException { |
|
474 return stdFileManager.getJavaFileForInput(location, className, kind); |
|
475 } |
|
476 |
|
477 /** |
|
478 * Returns a {@linkplain JavaFileObject file object} for output |
|
479 * representing the specified class of the specified kind in the |
|
480 * given location. |
|
481 * |
|
482 * <p>Optionally, this file manager might consider the sibling as |
|
483 * a hint for where to place the output. The exact semantics of |
|
484 * this hint is unspecified. The JDK compiler, javac, for |
|
485 * example, will place class files in the same directories as |
|
486 * originating source files unless a class file output directory |
|
487 * is provided. To facilitate this behavior, javac might provide |
|
488 * the originating source file as sibling when calling this |
|
489 * method. |
|
490 * |
|
491 * @param location a location |
|
492 * @param className the name of a class |
|
493 * @param kind the kind of file, must be one of {@link |
|
494 * JavaFileObject.Kind#SOURCE SOURCE} or {@link |
|
495 * JavaFileObject.Kind#CLASS CLASS} |
|
496 * @param sibling a file object to be used as hint for placement; |
|
497 * might be {@code null} |
|
498 * @return a file object for output |
|
499 * @throws IllegalArgumentException if sibling is not known to |
|
500 * this file manager, or if the location is not known to this file |
|
501 * manager and the file manager does not support unknown |
|
502 * locations, or if the kind is not valid |
|
503 * @throws IOException if an I/O error occurred, or if {@link |
|
504 * #close} has been called and this file manager cannot be |
|
505 * reopened |
|
506 * @throws IllegalStateException {@link #close} has been called |
|
507 * and this file manager cannot be reopened |
|
508 */ |
|
509 @Override @DefinedBy(Api.COMPILER) |
|
510 public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, |
|
511 String className, Kind kind, FileObject sibling) throws IOException { |
|
512 |
|
513 OutputMemoryJavaFileObject fo; |
|
514 fo = new OutputMemoryJavaFileObject(className, kind); |
|
515 classObjects.put(className, fo); |
|
516 proc.debug(DBG_FMGR, "Set out file: %s = %s\n", className, fo); |
|
517 if (classListener != null) { |
|
518 classListener.newClassFile(fo, location, className, kind, sibling); |
|
519 } |
|
520 return fo; |
|
521 } |
|
522 |
|
523 /** |
|
524 * Returns a {@linkplain FileObject file object} for input |
|
525 * representing the specified <a href="JavaFileManager.html#relative_name">relative |
|
526 * name</a> in the specified package in the given location. |
|
527 * |
|
528 * <p>If the returned object represents a {@linkplain |
|
529 * JavaFileObject.Kind#SOURCE source} or {@linkplain |
|
530 * JavaFileObject.Kind#CLASS class} file, it must be an instance |
|
531 * of {@link JavaFileObject}. |
|
532 * |
|
533 * <p>Informally, the file object returned by this method is |
|
534 * located in the concatenation of the location, package name, and |
|
535 * relative name. For example, to locate the properties file |
|
536 * "resources/compiler.properties" in the package |
|
537 * "com.sun.tools.javac" in the {@linkplain |
|
538 * StandardLocation#SOURCE_PATH SOURCE_PATH} location, this method |
|
539 * might be called like so: |
|
540 * |
|
541 * <pre>getFileForInput(SOURCE_PATH, "com.sun.tools.javac", "resources/compiler.properties");</pre> |
|
542 * |
|
543 * <p>If the call was executed on Windows, with SOURCE_PATH set to |
|
544 * <code>"C:\Documents and Settings\UncleBob\src\share\classes"</code>, |
|
545 * a valid result would be a file object representing the file |
|
546 * <code>"C:\Documents and Settings\UncleBob\src\share\classes\com\sun\tools\javac\resources\compiler.properties"</code>. |
|
547 * |
|
548 * @param location a location |
|
549 * @param packageName a package name |
|
550 * @param relativeName a relative name |
|
551 * @return a file object, might return {@code null} if the file |
|
552 * does not exist |
|
553 * @throws IllegalArgumentException if the location is not known |
|
554 * to this file manager and the file manager does not support |
|
555 * unknown locations, or if {@code relativeName} is not valid |
|
556 * @throws IOException if an I/O error occurred, or if {@link |
|
557 * #close} has been called and this file manager cannot be |
|
558 * reopened |
|
559 * @throws IllegalStateException if {@link #close} has been called |
|
560 * and this file manager cannot be reopened |
|
561 */ |
|
562 @Override @DefinedBy(Api.COMPILER) |
|
563 public FileObject getFileForInput(JavaFileManager.Location location, |
|
564 String packageName, |
|
565 String relativeName) |
|
566 throws IOException { |
|
567 proc.debug(DBG_FMGR, "getFileForInput location=%s packageName=%s\n", location, packageName); |
|
568 return stdFileManager.getFileForInput(location, packageName, relativeName); |
|
569 } |
|
570 |
|
571 /** |
|
572 * Returns a {@linkplain FileObject file object} for output |
|
573 * representing the specified <a href="JavaFileManager.html#relative_name">relative |
|
574 * name</a> in the specified package in the given location. |
|
575 * |
|
576 * <p>Optionally, this file manager might consider the sibling as |
|
577 * a hint for where to place the output. The exact semantics of |
|
578 * this hint is unspecified. The JDK compiler, javac, for |
|
579 * example, will place class files in the same directories as |
|
580 * originating source files unless a class file output directory |
|
581 * is provided. To facilitate this behavior, javac might provide |
|
582 * the originating source file as sibling when calling this |
|
583 * method. |
|
584 * |
|
585 * <p>If the returned object represents a {@linkplain |
|
586 * JavaFileObject.Kind#SOURCE source} or {@linkplain |
|
587 * JavaFileObject.Kind#CLASS class} file, it must be an instance |
|
588 * of {@link JavaFileObject}. |
|
589 * |
|
590 * <p>Informally, the file object returned by this method is |
|
591 * located in the concatenation of the location, package name, and |
|
592 * relative name or next to the sibling argument. See {@link |
|
593 * #getFileForInput getFileForInput} for an example. |
|
594 * |
|
595 * @param location a location |
|
596 * @param packageName a package name |
|
597 * @param relativeName a relative name |
|
598 * @param sibling a file object to be used as hint for placement; |
|
599 * might be {@code null} |
|
600 * @return a file object |
|
601 * @throws IllegalArgumentException if sibling is not known to |
|
602 * this file manager, or if the location is not known to this file |
|
603 * manager and the file manager does not support unknown |
|
604 * locations, or if {@code relativeName} is not valid |
|
605 * @throws IOException if an I/O error occurred, or if {@link |
|
606 * #close} has been called and this file manager cannot be |
|
607 * reopened |
|
608 * @throws IllegalStateException if {@link #close} has been called |
|
609 * and this file manager cannot be reopened |
|
610 */ |
|
611 @Override @DefinedBy(Api.COMPILER) |
|
612 public FileObject getFileForOutput(JavaFileManager.Location location, |
|
613 String packageName, |
|
614 String relativeName, |
|
615 FileObject sibling) |
|
616 throws IOException { |
|
617 throw new UnsupportedOperationException("getFileForOutput: location: " + location + |
|
618 ", packageName: " + packageName + |
|
619 ", relativeName: " + relativeName + |
|
620 ", sibling: " + sibling); |
|
621 } |
|
622 |
|
623 /** |
|
624 * Flushes any resources opened for output by this file manager |
|
625 * directly or indirectly. Flushing a closed file manager has no |
|
626 * effect. |
|
627 * |
|
628 * @throws IOException if an I/O error occurred |
|
629 * @see #close |
|
630 */ |
|
631 @Override @DefinedBy(Api.COMPILER) |
|
632 public void flush() throws IOException { |
|
633 // Nothing to flush |
|
634 } |
|
635 |
|
636 /** |
|
637 * Releases any resources opened by this file manager directly or |
|
638 * indirectly. This might render this file manager useless and |
|
639 * the effect of subsequent calls to methods on this object or any |
|
640 * objects obtained through this object is undefined unless |
|
641 * explicitly allowed. However, closing a file manager which has |
|
642 * already been closed has no effect. |
|
643 * |
|
644 * @throws IOException if an I/O error occurred |
|
645 * @see #flush |
|
646 */ |
|
647 @Override @DefinedBy(Api.COMPILER) |
|
648 public void close() throws IOException { |
|
649 // Nothing to close |
|
650 } |
|
651 } |