View Javadoc

1   /*
2   	Copyright (c) 2009 Olivier Chafik, All Rights Reserved
3   	
4   	This file is part of JNAerator (http://jnaerator.googlecode.com/).
5   	
6   	JNAerator is free software: you can redistribute it and/or modify
7   	it under the terms of the GNU General Public License as published by
8   	the Free Software Foundation, either version 3 of the License, or
9   	(at your option) any later version.
10  	
11  	JNAerator is distributed in the hope that it will be useful,
12  	but WITHOUT ANY WARRANTY; without even the implied warranty of
13  	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  	GNU General Public License for more details.
15  	
16  	You should have received a copy of the GNU General Public License
17  	along with JNAerator.  If not, see <http://www.gnu.org/licenses/>.
18  */
19  package com.ochafik.lang.compiler;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FileNotFoundException;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  import java.util.ArrayList;
29  import java.util.HashMap;
30  import java.util.Map;
31  import java.util.jar.JarEntry;
32  import java.util.jar.JarOutputStream;
33  
34  import javax.tools.FileObject;
35  import javax.tools.ForwardingJavaFileManager;
36  import javax.tools.JavaFileManager;
37  import javax.tools.JavaFileObject;
38  
39  import com.ochafik.io.IOUtils;
40  
41  
42  public class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
43  	public final Map<String, MemoryJavaFile> inputs = new HashMap<String, MemoryJavaFile>();
44  	public final Map<String, FileObject> outputs = new HashMap<String, FileObject>();
45  
46  	public void writeJar(File outputJar, boolean outputSources, Map<String, File> additionalFiles) throws IOException {
47  
48  		File jarDir = outputJar.getAbsoluteFile().getParentFile();
49  		if (!jarDir.isDirectory())
50  			jarDir.mkdirs();
51  		writeJar(new FileOutputStream(outputJar), outputSources, additionalFiles);
52  	}
53  	public void writeJar(OutputStream out, boolean outputSources, Map<String, File> additionalFiles) throws IOException {
54  		JarOutputStream jout = new JarOutputStream(out);
55  		if (outputSources)
56  			for (Map.Entry<String, MemoryJavaFile> e : inputs.entrySet()) {
57  //				if (e.getKey().contains(".class"))
58  //					continue;
59  				writeEntry(e.getKey(), e.getValue(), jout);
60  			}
61  		for (Map.Entry<String, FileObject> e : outputs.entrySet())
62  			writeEntry(e.getKey(), e.getValue(), jout);
63  		
64  		if (additionalFiles != null)
65  			for (Map.Entry<String, File> additionalFile : additionalFiles.entrySet()) {
66  				String path = additionalFile.getKey();
67  				if (path.startsWith("file:///"))
68  					path = path.substring("file:///".length());
69  
70  				FileInputStream in = new FileInputStream(additionalFile.getValue());
71  				JarEntry e = new JarEntry(path);
72  				jout.putNextEntry(e);
73  				IOUtils.readWrite(in, jout);
74  				in.close();
75  				jout.closeEntry();
76  			}
77  		jout.close();
78  	}
79  	protected void writeEntry(String path, FileObject o, JarOutputStream jout) throws IOException {
80  		if (path.startsWith("/"))
81  			path = path.substring(1);
82  		if (path.startsWith("file:///"))
83  			path = path.substring("file:///".length());
84  
85  		if (o instanceof MemoryFileObject) {
86  			MemoryFileObject mo = (MemoryFileObject)o;
87  			byte[] c = mo.getContent();
88  			if (c == null)
89  				return;
90  	
91  //			String path = mo.getPath();
92  //			if (path.startsWith("file:///"))
93  //				path = path.substring("file:///".length());
94  			JarEntry e = new JarEntry(path);
95  			jout.putNextEntry(e);
96  			jout.write(c);
97  			jout.closeEntry();
98  		} else if (o instanceof URLFileObject) {
99  			URLFileObject uo = (URLFileObject)o;
100 //			String path = uo.url.getFile();
101 //			if (path.startsWith("/"))
102 //				path = path.substring(1);
103 			
104 			JarEntry e = new JarEntry(path);
105 			jout.putNextEntry(e);
106 			InputStream in = uo.url.openStream();
107 			if (in == null)
108 				throw new FileNotFoundException(path);
109 			IOUtils.readWrite(in, jout);
110 			in.close();
111 			jout.closeEntry();
112 		} else
113 			throw new UnsupportedOperationException("Dunno how to deal with " + o);
114 	}
115 	public MemoryFileManager(JavaFileManager fm) {
116 		super(fm);
117 	}
118 
119 	public MemoryJavaFile addSourceInput(String path, String content) {
120 		if (!path.startsWith("file:///"))
121 			path = "file:///" + path;
122 		
123 		MemoryJavaFile mjf = new MemoryJavaFile(path, content, JavaFileObject.Kind.SOURCE);
124 		inputs.put(path, mjf);
125 		return mjf;
126 	}
127 	@Override
128 	public boolean isSameFile(FileObject a, FileObject b) {
129 		return a.toString().equals(b.toString());
130 	}
131 	public Iterable<? extends JavaFileObject> getJavaFileObjects() {
132 		return new ArrayList<JavaFileObject>(inputs.values());
133 	}
134 
135 	@Override
136 	public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
137 //		System.out.println("getJavaFileForInput(className = " + className + ", location = " + location + ", kind = " + kind + ")");
138 		if (kind == JavaFileObject.Kind.SOURCE) {
139 			return inputs.get(className);
140 		}
141 		return super.getJavaFileForInput(location, className, kind);
142 	}
143 
144 	public static String getFullPathForClass(String className, String extension) {
145 		return "file:///" + getSimplePathForClass(className, extension);
146 	}
147 	public static String getSimplePathForClass(String className, String extension) {
148 		return className.replace('.', '/') + "." + extension;
149 	}
150 	@Override
151 	public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
152 //		System.out.println("getJavaFileForOutput(className = " + className + ", location = " + location + ", kind = " + kind + ")");
153 		MemoryJavaFile jo = null;
154 		if (kind == JavaFileObject.Kind.CLASS) {
155 			outputs.put(getFullPathForClass(className, "class"), jo = new MemoryJavaFile(getFullPathForClass(className, "class"), null, kind));
156 		} else if (kind == JavaFileObject.Kind.SOURCE) {
157 			inputs.put(getFullPathForClass(className, "java"), jo = new MemoryJavaFile(getFullPathForClass(className, "java"), null, kind));
158 		}
159 
160 		return jo == null ? super.getJavaFileForInput(location, className, kind) : jo;
161 	}
162 	@Override
163 	public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
164 //		System.out.println("getFileForOutput(relativeName = " + relativeName + ")");
165 		if (relativeName.startsWith("file:///"))
166 			relativeName = relativeName.substring("file:///".length());
167 		
168 		FileObject out = outputs.get(relativeName);
169 		if (out == null) {
170 			out = new MemoryFileObject(relativeName, (String)null);
171 			outputs.put(relativeName, out);
172 		}
173 		return out;
174 	}
175 }