|
1 /* |
|
2 * Copyright (c) 2005, 2011, 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 com.sun.tools.javac.file; |
|
27 |
|
28 import java.io.IOException; |
|
29 import java.util.Set; |
|
30 import javax.tools.JavaFileObject; |
|
31 |
|
32 import java.io.ByteArrayInputStream; |
|
33 import java.io.File; |
|
34 import java.io.InputStream; |
|
35 import java.io.OutputStream; |
|
36 import java.io.Writer; |
|
37 import java.net.URI; |
|
38 import java.nio.ByteBuffer; |
|
39 import java.nio.CharBuffer; |
|
40 import java.nio.charset.CharsetDecoder; |
|
41 |
|
42 import com.sun.tools.javac.file.JavacFileManager.Archive; |
|
43 import com.sun.tools.javac.file.RelativePath.RelativeDirectory; |
|
44 import com.sun.tools.javac.file.RelativePath.RelativeFile; |
|
45 import com.sun.tools.javac.util.Assert; |
|
46 import com.sun.tools.javac.util.List; |
|
47 |
|
48 /** |
|
49 * <p><b>This is NOT part of any supported API. |
|
50 * If you write code that depends on this, you do so at your own risk. |
|
51 * This code and its internal interfaces are subject to change or |
|
52 * deletion without notice.</b> |
|
53 */ |
|
54 public class ZipFileIndexArchive implements Archive { |
|
55 |
|
56 private final ZipFileIndex zfIndex; |
|
57 private JavacFileManager fileManager; |
|
58 |
|
59 public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException { |
|
60 super(); |
|
61 this.fileManager = fileManager; |
|
62 this.zfIndex = zdir; |
|
63 } |
|
64 |
|
65 public boolean contains(RelativePath name) { |
|
66 return zfIndex.contains(name); |
|
67 } |
|
68 |
|
69 public List<String> getFiles(RelativeDirectory subdirectory) { |
|
70 return zfIndex.getFiles(subdirectory); |
|
71 } |
|
72 |
|
73 public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) { |
|
74 RelativeFile fullZipFileName = new RelativeFile(subdirectory, file); |
|
75 ZipFileIndex.Entry entry = zfIndex.getZipIndexEntry(fullZipFileName); |
|
76 JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile()); |
|
77 return ret; |
|
78 } |
|
79 |
|
80 public Set<RelativeDirectory> getSubdirectories() { |
|
81 return zfIndex.getAllDirectories(); |
|
82 } |
|
83 |
|
84 public void close() throws IOException { |
|
85 zfIndex.close(); |
|
86 } |
|
87 |
|
88 @Override |
|
89 public String toString() { |
|
90 return "ZipFileIndexArchive[" + zfIndex + "]"; |
|
91 } |
|
92 |
|
93 /** |
|
94 * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.file.ZipFileIndex implementation. |
|
95 */ |
|
96 public static class ZipFileIndexFileObject extends BaseFileObject { |
|
97 |
|
98 /** The entry's name. |
|
99 */ |
|
100 private String name; |
|
101 |
|
102 /** The zipfile containing the entry. |
|
103 */ |
|
104 ZipFileIndex zfIndex; |
|
105 |
|
106 /** The underlying zip entry object. |
|
107 */ |
|
108 ZipFileIndex.Entry entry; |
|
109 |
|
110 /** The InputStream for this zip entry (file.) |
|
111 */ |
|
112 InputStream inputStream = null; |
|
113 |
|
114 /** The name of the zip file where this entry resides. |
|
115 */ |
|
116 File zipName; |
|
117 |
|
118 |
|
119 ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, File zipFileName) { |
|
120 super(fileManager); |
|
121 this.name = entry.getFileName(); |
|
122 this.zfIndex = zfIndex; |
|
123 this.entry = entry; |
|
124 this.zipName = zipFileName; |
|
125 } |
|
126 |
|
127 @Override |
|
128 public URI toUri() { |
|
129 return createJarUri(zipName, getPrefixedEntryName()); |
|
130 } |
|
131 |
|
132 @Override |
|
133 public String getName() { |
|
134 return zipName + "(" + getPrefixedEntryName() + ")"; |
|
135 } |
|
136 |
|
137 @Override |
|
138 public String getShortName() { |
|
139 return zipName.getName() + "(" + entry.getName() + ")"; |
|
140 } |
|
141 |
|
142 @Override |
|
143 public JavaFileObject.Kind getKind() { |
|
144 return getKind(entry.getName()); |
|
145 } |
|
146 |
|
147 @Override |
|
148 public InputStream openInputStream() throws IOException { |
|
149 if (inputStream == null) { |
|
150 Assert.checkNonNull(entry); // see constructor |
|
151 inputStream = new ByteArrayInputStream(zfIndex.read(entry)); |
|
152 } |
|
153 return inputStream; |
|
154 } |
|
155 |
|
156 @Override |
|
157 public OutputStream openOutputStream() throws IOException { |
|
158 throw new UnsupportedOperationException(); |
|
159 } |
|
160 |
|
161 @Override |
|
162 public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { |
|
163 CharBuffer cb = fileManager.getCachedContent(this); |
|
164 if (cb == null) { |
|
165 InputStream in = new ByteArrayInputStream(zfIndex.read(entry)); |
|
166 try { |
|
167 ByteBuffer bb = fileManager.makeByteBuffer(in); |
|
168 JavaFileObject prev = fileManager.log.useSource(this); |
|
169 try { |
|
170 cb = fileManager.decode(bb, ignoreEncodingErrors); |
|
171 } finally { |
|
172 fileManager.log.useSource(prev); |
|
173 } |
|
174 fileManager.recycleByteBuffer(bb); // save for next time |
|
175 if (!ignoreEncodingErrors) |
|
176 fileManager.cache(this, cb); |
|
177 } finally { |
|
178 in.close(); |
|
179 } |
|
180 } |
|
181 return cb; |
|
182 } |
|
183 |
|
184 @Override |
|
185 public Writer openWriter() throws IOException { |
|
186 throw new UnsupportedOperationException(); |
|
187 } |
|
188 |
|
189 @Override |
|
190 public long getLastModified() { |
|
191 return entry.getLastModified(); |
|
192 } |
|
193 |
|
194 @Override |
|
195 public boolean delete() { |
|
196 throw new UnsupportedOperationException(); |
|
197 } |
|
198 |
|
199 @Override |
|
200 protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) { |
|
201 return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors); |
|
202 } |
|
203 |
|
204 @Override |
|
205 protected String inferBinaryName(Iterable<? extends File> path) { |
|
206 String entryName = entry.getName(); |
|
207 if (zfIndex.symbolFilePrefix != null) { |
|
208 String prefix = zfIndex.symbolFilePrefix.path; |
|
209 if (entryName.startsWith(prefix)) |
|
210 entryName = entryName.substring(prefix.length()); |
|
211 } |
|
212 return removeExtension(entryName).replace('/', '.'); |
|
213 } |
|
214 |
|
215 @Override |
|
216 public boolean isNameCompatible(String cn, JavaFileObject.Kind k) { |
|
217 cn.getClass(); // null check |
|
218 if (k == Kind.OTHER && getKind() != k) |
|
219 return false; |
|
220 return name.equals(cn + k.extension); |
|
221 } |
|
222 |
|
223 /** |
|
224 * Check if two file objects are equal. |
|
225 * Two ZipFileIndexFileObjects are equal if the absolute paths of the underlying |
|
226 * zip files are equal and if the paths within those zip files are equal. |
|
227 */ |
|
228 @Override |
|
229 public boolean equals(Object other) { |
|
230 if (this == other) |
|
231 return true; |
|
232 |
|
233 if (!(other instanceof ZipFileIndexFileObject)) |
|
234 return false; |
|
235 |
|
236 ZipFileIndexFileObject o = (ZipFileIndexFileObject) other; |
|
237 return zfIndex.getAbsoluteFile().equals(o.zfIndex.getAbsoluteFile()) |
|
238 && name.equals(o.name); |
|
239 } |
|
240 |
|
241 @Override |
|
242 public int hashCode() { |
|
243 return zfIndex.getAbsoluteFile().hashCode() + name.hashCode(); |
|
244 } |
|
245 |
|
246 private String getPrefixedEntryName() { |
|
247 if (zfIndex.symbolFilePrefix != null) |
|
248 return zfIndex.symbolFilePrefix.path + entry.getName(); |
|
249 else |
|
250 return entry.getName(); |
|
251 } |
|
252 } |
|
253 |
|
254 } |