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
46 import javax.tools.JavaFileObject.Kind;
47 import static javax.tools.StandardLocation.CLASS_PATH;
48 import javax.tools.FileObject;
49 import javax.tools.JavaFileManager;
50 import javax.tools.JavaFileObject;
51 import javax.tools.SimpleJavaFileObject;
52 import javax.tools.StandardJavaFileManager;
53 import javax.tools.StandardLocation;
54
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 JShell proc;
73
74 // Upcoming Jigsaw
75 private Method inferModuleNameMethod = null;
76 private Method listLocationsForModulesMethod = null;
77
78 Iterable<? extends Path> getLocationAsPaths(Location loc) {
79 return this.stdFileManager.getLocationAsPaths(loc);
80 }
81
82 static abstract class MemoryJavaFileObject extends SimpleJavaFileObject {
83
84 public MemoryJavaFileObject(String name, JavaFileObject.Kind kind) {
85 super(URI.create("string:///" + name.replace('.', '/')
86 + kind.extension), kind);
87 }
88 }
89
90 class SourceMemoryJavaFileObject extends MemoryJavaFileObject {
91 private final String src;
92 private final Object origin;
93
94 SourceMemoryJavaFileObject(Object origin, String className, String code) {
95 super(className, JavaFileObject.Kind.SOURCE);
96 this.origin = origin;
97 this.src = code;
167 public MemoryFileManager(StandardJavaFileManager standardManager, JShell proc) {
168 this.stdFileManager = standardManager;
169 this.proc = proc;
170 }
171
172 private Collection<OutputMemoryJavaFileObject> generatedClasses() {
173 return classObjects.values();
174 }
175
176 // For debugging dumps
177 public void dumpClasses() {
178 for (OutputMemoryJavaFileObject co : generatedClasses()) {
179 co.dump();
180 }
181 }
182
183 public JavaFileObject createSourceFileObject(Object origin, String name, String code) {
184 return new SourceMemoryJavaFileObject(origin, name, code);
185 }
186
187 // Make compatible with Jigsaw
188 public String inferModuleName(Location location) {
189 try {
190 if (inferModuleNameMethod == null) {
191 inferModuleNameMethod = JavaFileManager.class.getDeclaredMethod("inferModuleName", Location.class);
192 }
193 @SuppressWarnings("unchecked")
194 String result = (String) inferModuleNameMethod.invoke(stdFileManager, location);
195 return result;
196 } catch (NoSuchMethodException | SecurityException ex) {
197 throw new InternalError("Cannot lookup JavaFileManager method", ex);
198 } catch (IllegalAccessException |
199 IllegalArgumentException |
200 InvocationTargetException ex) {
201 throw new InternalError("Cannot invoke JavaFileManager method", ex);
202 }
203 }
204
205 // Make compatible with Jigsaw
206 public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException {
207 try {
208 if (listLocationsForModulesMethod == null) {
209 listLocationsForModulesMethod = JavaFileManager.class.getDeclaredMethod("listLocationsForModules", Location.class);
210 }
211 @SuppressWarnings("unchecked")
212 Iterable<Set<Location>> result = (Iterable<Set<Location>>) listLocationsForModulesMethod.invoke(stdFileManager, location);
213 return result;
214 } catch (NoSuchMethodException | SecurityException ex) {
215 throw new InternalError("Cannot lookup JavaFileManager method", ex);
216 } catch (IllegalAccessException |
217 IllegalArgumentException |
218 InvocationTargetException ex) {
219 throw new InternalError("Cannot invoke JavaFileManager method", ex);
220 }
221 }
222
223
224 /**
225 * Returns a class loader for loading plug-ins from the given location. For
226 * example, to load annotation processors, a compiler will request a class
227 * loader for the {@link
228 * StandardLocation#ANNOTATION_PROCESSOR_PATH
229 * ANNOTATION_PROCESSOR_PATH} location.
230 *
231 * @param location a location
232 * @return a class loader for the given location; or {@code null}
233 * if loading plug-ins from the given location is disabled or if
234 * the location is not known
235 * @throws SecurityException if a class loader can not be created
236 * in the current security context
237 * @throws IllegalStateException if {@link #close} has been called
238 * and this file manager cannot be reopened
239 */
240 @Override
241 public ClassLoader getClassLoader(JavaFileManager.Location location) {
242 proc.debug(DBG_FMGR, "getClassLoader: location\n", location);
243 return stdFileManager.getClassLoader(location);
561 * @throws IllegalArgumentException if sibling is not known to
562 * this file manager, or if the location is not known to this file
563 * manager and the file manager does not support unknown
564 * locations, or if {@code relativeName} is not valid
565 * @throws IOException if an I/O error occurred, or if {@link
566 * #close} has been called and this file manager cannot be
567 * reopened
568 * @throws IllegalStateException if {@link #close} has been called
569 * and this file manager cannot be reopened
570 */
571 @Override
572 public FileObject getFileForOutput(JavaFileManager.Location location,
573 String packageName,
574 String relativeName,
575 FileObject sibling)
576 throws IOException {
577 throw new UnsupportedOperationException("getFileForOutput: location: " + location +
578 ", packageName: " + packageName +
579 ", relativeName: " + relativeName +
580 ", sibling: " + sibling);
581 }
582
583 /**
584 * Flushes any resources opened for output by this file manager
585 * directly or indirectly. Flushing a closed file manager has no
586 * effect.
587 *
588 * @throws IOException if an I/O error occurred
589 * @see #close
590 */
591 @Override
592 public void flush() throws IOException {
593 // Nothing to flush
594 }
595
596 /**
597 * Releases any resources opened by this file manager directly or
598 * indirectly. This might render this file manager useless and
599 * the effect of subsequent calls to methods on this object or any
600 * objects obtained through this object is undefined unless
|
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.net.URI;
34 import java.nio.file.FileSystems;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.util.Collection;
38 import java.util.Iterator;
39 import java.util.Map;
40 import java.util.NoSuchElementException;
41 import java.util.Set;
42 import java.util.TreeMap;
43
44 import javax.tools.JavaFileObject.Kind;
45 import static javax.tools.StandardLocation.CLASS_PATH;
46 import javax.tools.FileObject;
47 import javax.tools.JavaFileManager;
48 import javax.tools.JavaFileObject;
49 import javax.tools.SimpleJavaFileObject;
50 import javax.tools.StandardJavaFileManager;
51 import javax.tools.StandardLocation;
52
53
54 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_FMGR;
55
56 /**
57 * File manager for the compiler API. Reads from memory (Strings) and writes
58 * class files to memory (cached OutputMemoryJavaFileObject).
59 *
60 * @author Robert Field
61 */
62 class MemoryFileManager implements JavaFileManager {
63
64 private final StandardJavaFileManager stdFileManager;
65
66 private final Map<String, OutputMemoryJavaFileObject> classObjects = new TreeMap<>();
67
68 private ClassFileCreationListener classListener = null;
69
70 private final JShell proc;
71
72 Iterable<? extends Path> getLocationAsPaths(Location loc) {
73 return this.stdFileManager.getLocationAsPaths(loc);
74 }
75
76 static abstract class MemoryJavaFileObject extends SimpleJavaFileObject {
77
78 public MemoryJavaFileObject(String name, JavaFileObject.Kind kind) {
79 super(URI.create("string:///" + name.replace('.', '/')
80 + kind.extension), kind);
81 }
82 }
83
84 class SourceMemoryJavaFileObject extends MemoryJavaFileObject {
85 private final String src;
86 private final Object origin;
87
88 SourceMemoryJavaFileObject(Object origin, String className, String code) {
89 super(className, JavaFileObject.Kind.SOURCE);
90 this.origin = origin;
91 this.src = code;
161 public MemoryFileManager(StandardJavaFileManager standardManager, JShell proc) {
162 this.stdFileManager = standardManager;
163 this.proc = proc;
164 }
165
166 private Collection<OutputMemoryJavaFileObject> generatedClasses() {
167 return classObjects.values();
168 }
169
170 // For debugging dumps
171 public void dumpClasses() {
172 for (OutputMemoryJavaFileObject co : generatedClasses()) {
173 co.dump();
174 }
175 }
176
177 public JavaFileObject createSourceFileObject(Object origin, String name, String code) {
178 return new SourceMemoryJavaFileObject(origin, name, code);
179 }
180
181 /**
182 * Returns a class loader for loading plug-ins from the given location. For
183 * example, to load annotation processors, a compiler will request a class
184 * loader for the {@link
185 * StandardLocation#ANNOTATION_PROCESSOR_PATH
186 * ANNOTATION_PROCESSOR_PATH} location.
187 *
188 * @param location a location
189 * @return a class loader for the given location; or {@code null}
190 * if loading plug-ins from the given location is disabled or if
191 * the location is not known
192 * @throws SecurityException if a class loader can not be created
193 * in the current security context
194 * @throws IllegalStateException if {@link #close} has been called
195 * and this file manager cannot be reopened
196 */
197 @Override
198 public ClassLoader getClassLoader(JavaFileManager.Location location) {
199 proc.debug(DBG_FMGR, "getClassLoader: location\n", location);
200 return stdFileManager.getClassLoader(location);
518 * @throws IllegalArgumentException if sibling is not known to
519 * this file manager, or if the location is not known to this file
520 * manager and the file manager does not support unknown
521 * locations, or if {@code relativeName} is not valid
522 * @throws IOException if an I/O error occurred, or if {@link
523 * #close} has been called and this file manager cannot be
524 * reopened
525 * @throws IllegalStateException if {@link #close} has been called
526 * and this file manager cannot be reopened
527 */
528 @Override
529 public FileObject getFileForOutput(JavaFileManager.Location location,
530 String packageName,
531 String relativeName,
532 FileObject sibling)
533 throws IOException {
534 throw new UnsupportedOperationException("getFileForOutput: location: " + location +
535 ", packageName: " + packageName +
536 ", relativeName: " + relativeName +
537 ", sibling: " + sibling);
538 }
539
540 @Override
541 public Location getLocationForModule(Location location, String moduleName) throws IOException {
542 return stdFileManager.getLocationForModule(location, moduleName);
543 }
544
545 @Override
546 public Location getLocationForModule(Location location, JavaFileObject fo, String pkgName) throws IOException {
547 return stdFileManager.getLocationForModule(location, fo, pkgName);
548 }
549
550 @Override
551 public String inferModuleName(Location location) throws IOException {
552 return stdFileManager.inferModuleName(location);
553 }
554
555 @Override
556 public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException {
557 return stdFileManager.listLocationsForModules(location);
558 }
559
560 /**
561 * Flushes any resources opened for output by this file manager
562 * directly or indirectly. Flushing a closed file manager has no
563 * effect.
564 *
565 * @throws IOException if an I/O error occurred
566 * @see #close
567 */
568 @Override
569 public void flush() throws IOException {
570 // Nothing to flush
571 }
572
573 /**
574 * Releases any resources opened by this file manager directly or
575 * indirectly. This might render this file manager useless and
576 * the effect of subsequent calls to methods on this object or any
577 * objects obtained through this object is undefined unless
|