001/* 002 * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 003 * Use is subject to license terms. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, are 006 * permitted provided that the following conditions are met: Redistributions of source code 007 * must retain the above copyright notice, this list of conditions and the following disclaimer. 008 * Redistributions in binary form must reproduce the above copyright notice, this list of 009 * conditions and the following disclaimer in the documentation and/or other materials 010 * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 011 * is contributors may be used to endorse or promote products derived from this software 012 * without specific prior written permission. 013 014 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 015 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 016 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 017 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 018 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 019 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 020 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 021 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 022 * POSSIBILITY OF SUCH DAMAGE. 023 */ 024 025/* 026 * MemoryJavaFileManager.java 027 * @author A. Sundararajan 028 */ 029 030package org.kepler.scriptengine.java; 031 032import java.io.ByteArrayOutputStream; 033import java.io.File; 034import java.io.FilterOutputStream; 035import java.io.IOException; 036import java.io.OutputStream; 037import java.net.URI; 038import java.nio.CharBuffer; 039import java.util.HashMap; 040import java.util.Map; 041 042import javax.tools.FileObject; 043import javax.tools.ForwardingJavaFileManager; 044import javax.tools.JavaFileManager; 045import javax.tools.JavaFileObject; 046import javax.tools.JavaFileObject.Kind; 047import javax.tools.SimpleJavaFileObject; 048 049/** 050 * JavaFileManager that keeps compiled .class bytes in memory. 051 */ 052public final class MemoryJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> { 053 054 /** Java source file extension. */ 055 private final static String EXT = ".java"; 056 057 private Map<String, byte[]> classBytes; 058 059 public MemoryJavaFileManager(JavaFileManager fileManager) { 060 super(fileManager); 061 classBytes = new HashMap<String, byte[]>(); 062 } 063 064 public Map<String, byte[]> getClassBytes() { 065 return classBytes; 066 } 067 068 @Override 069 public void close() throws IOException { 070 classBytes = new HashMap<String, byte[]>(); 071 } 072 073 @Override 074 public void flush() throws IOException { 075 } 076 077 /** 078 * A file object used to represent Java source coming from a string. 079 */ 080 private static class StringInputBuffer extends SimpleJavaFileObject { 081 final String code; 082 083 StringInputBuffer(String name, String code) { 084 super(toURI(name), Kind.SOURCE); 085 this.code = code; 086 } 087 088 @Override 089 public CharBuffer getCharContent(boolean ignoreEncodingErrors) { 090 return CharBuffer.wrap(code); 091 } 092 093 /* 094 public Reader openReader() { 095 return new StringReader(code); 096 } 097 */ 098 } 099 100 /** 101 * A file object that stores Java bytecode into the classBytes map. 102 */ 103 private class ClassOutputBuffer extends SimpleJavaFileObject { 104 private String name; 105 106 ClassOutputBuffer(String name) { 107 super(toURI(name), Kind.CLASS); 108 this.name = name; 109 } 110 111 @Override 112 public OutputStream openOutputStream() { 113 return new FilterOutputStream(new ByteArrayOutputStream()) { 114 @Override 115 public void close() throws IOException { 116 out.close(); 117 ByteArrayOutputStream bos = (ByteArrayOutputStream)out; 118 classBytes.put(name, bos.toByteArray()); 119 } 120 }; 121 } 122 } 123 124 @Override 125 public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, 126 String className, 127 Kind kind, 128 FileObject sibling) throws IOException { 129 if (kind == Kind.CLASS) { 130 return new ClassOutputBuffer(className); 131 } else { 132 return super.getJavaFileForOutput(location, className, kind, sibling); 133 } 134 } 135 136 static JavaFileObject makeStringSource(String name, String code) { 137 return new StringInputBuffer(name, code); 138 } 139 140 static URI toURI(String name) { 141 File file = new File(name); 142 if (file.exists()) { 143 return file.toURI(); 144 } else { 145 try { 146 final StringBuilder newUri = new StringBuilder(); 147 newUri.append("mfm:///"); 148 newUri.append(name.replace('.', '/')); 149 if(name.endsWith(EXT)) newUri.replace(newUri.length() - EXT.length(), newUri.length(), EXT); 150 return URI.create(newUri.toString()); 151 } catch (Exception exp) { 152 return URI.create("mfm:///com/sun/script/java/java_source"); 153 } 154 } 155 } 156}