Tue, 26 Aug 2008 14:52:59 -0700
6508981: cleanup file separator handling in JavacFileManager
Reviewed-by: mcimadamore
1 /*
2 * Copyright 2005-2008 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.javac.file;
28 import java.io.File;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.OutputStream;
32 import java.io.Writer;
33 import java.net.URI;
34 import java.nio.ByteBuffer;
35 import java.nio.CharBuffer;
36 import java.nio.charset.CharsetDecoder;
37 import java.util.Enumeration;
38 import java.util.HashMap;
39 import java.util.Map;
40 import java.util.Set;
41 import java.util.zip.ZipEntry;
42 import java.util.zip.ZipFile;
44 import javax.tools.JavaFileObject;
46 import com.sun.tools.javac.file.JavacFileManager.Archive;
47 import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
48 import com.sun.tools.javac.file.RelativePath.RelativeFile;
49 import com.sun.tools.javac.util.List;
51 public class ZipArchive implements Archive {
53 public ZipArchive(JavacFileManager fm, ZipFile zdir) throws IOException {
54 this(fm, zdir, true);
55 }
57 protected ZipArchive(JavacFileManager fm, ZipFile zdir, boolean initMap) throws IOException {
58 this.fileManager = fm;
59 this.zdir = zdir;
60 this.map = new HashMap<RelativeDirectory,List<String>>();
61 if (initMap)
62 initMap();
63 }
65 protected void initMap() throws IOException {
66 for (Enumeration<? extends ZipEntry> e = zdir.entries(); e.hasMoreElements(); ) {
67 ZipEntry entry;
68 try {
69 entry = e.nextElement();
70 } catch (InternalError ex) {
71 IOException io = new IOException();
72 io.initCause(ex); // convenience constructors added in Mustang :-(
73 throw io;
74 }
75 addZipEntry(entry);
76 }
77 }
79 void addZipEntry(ZipEntry entry) {
80 String name = entry.getName();
81 int i = name.lastIndexOf('/');
82 RelativeDirectory dirname = new RelativeDirectory(name.substring(0, i+1));
83 String basename = name.substring(i+1);
84 if (basename.length() == 0)
85 return;
86 List<String> list = map.get(dirname);
87 if (list == null)
88 list = List.nil();
89 list = list.prepend(basename);
90 map.put(dirname, list);
91 }
93 public boolean contains(RelativePath name) {
94 RelativeDirectory dirname = name.dirname();
95 String basename = name.basename();
96 if (basename.length() == 0)
97 return false;
98 List<String> list = map.get(dirname);
99 return (list != null && list.contains(basename));
100 }
102 public List<String> getFiles(RelativeDirectory subdirectory) {
103 return map.get(subdirectory);
104 }
106 public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
107 ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zdir);
108 return new ZipFileObject(this, file, ze);
109 }
111 public Set<RelativeDirectory> getSubdirectories() {
112 return map.keySet();
113 }
115 public void close() throws IOException {
116 zdir.close();
117 }
119 public String toString() {
120 return "ZipArchive[" + zdir.getName() + "]";
121 }
123 protected JavacFileManager fileManager;
124 protected final Map<RelativeDirectory,List<String>> map;
125 protected final ZipFile zdir;
127 /**
128 * A subclass of JavaFileObject representing zip entries.
129 */
130 public static class ZipFileObject extends BaseFileObject {
132 private String name;
133 ZipArchive zarch;
134 ZipEntry entry;
136 protected ZipFileObject(ZipArchive zarch, String name, ZipEntry entry) {
137 super(zarch.fileManager);
138 this.zarch = zarch;
139 this.name = name;
140 this.entry = entry;
141 }
143 public InputStream openInputStream() throws IOException {
144 return zarch.zdir.getInputStream(entry);
145 }
147 public OutputStream openOutputStream() throws IOException {
148 throw new UnsupportedOperationException();
149 }
151 protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
152 return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
153 }
155 public Writer openWriter() throws IOException {
156 throw new UnsupportedOperationException();
157 }
159 @Deprecated
160 public String getName() {
161 return name;
162 }
164 public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
165 cn.getClass();
166 // null check
167 if (k == Kind.OTHER && getKind() != k) {
168 return false;
169 }
170 return name.equals(cn + k.extension);
171 }
173 @Deprecated
174 public String getPath() {
175 return zarch.zdir.getName() + "(" + entry + ")";
176 }
178 public long getLastModified() {
179 return entry.getTime();
180 }
182 public boolean delete() {
183 throw new UnsupportedOperationException();
184 }
186 public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
187 CharBuffer cb = fileManager.getCachedContent(this);
188 if (cb == null) {
189 InputStream in = zarch.zdir.getInputStream(entry);
190 try {
191 ByteBuffer bb = fileManager.makeByteBuffer(in);
192 JavaFileObject prev = fileManager.log.useSource(this);
193 try {
194 cb = fileManager.decode(bb, ignoreEncodingErrors);
195 } finally {
196 fileManager.log.useSource(prev);
197 }
198 fileManager.recycleByteBuffer(bb);
199 if (!ignoreEncodingErrors) {
200 fileManager.cache(this, cb);
201 }
202 } finally {
203 in.close();
204 }
205 }
206 return cb;
207 }
209 @Override
210 public boolean equals(Object other) {
211 if (!(other instanceof ZipFileObject)) {
212 return false;
213 }
214 ZipFileObject o = (ZipFileObject) other;
215 return zarch.zdir.equals(o.zarch.zdir) || name.equals(o.name);
216 }
218 @Override
219 public int hashCode() {
220 return zarch.zdir.hashCode() + name.hashCode();
221 }
223 public String getZipName() {
224 return zarch.zdir.getName();
225 }
227 public String getZipEntryName() {
228 return entry.getName();
229 }
231 public URI toUri() {
232 String zipName = new File(getZipName()).toURI().normalize().getPath();
233 String entryName = getZipEntryName();
234 return URI.create("jar:" + zipName + "!" + entryName);
235 }
237 @Override
238 protected String inferBinaryName(Iterable<? extends File> path) {
239 String entryName = getZipEntryName();
240 return removeExtension(entryName).replace('/', '.');
241 }
242 }
244 }