Fri, 25 Sep 2009 22:04:43 -0700
Merge
1 /*
2 * Copyright 2005-2009 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 /**
52 * <p><b>This is NOT part of any API supported by Sun Microsystems.
53 * If you write code that depends on this, you do so at your own risk.
54 * This code and its internal interfaces are subject to change or
55 * deletion without notice.</b>
56 */
57 public class ZipArchive implements Archive {
59 public ZipArchive(JavacFileManager fm, ZipFile zdir) throws IOException {
60 this(fm, zdir, true);
61 }
63 protected ZipArchive(JavacFileManager fm, ZipFile zdir, boolean initMap) throws IOException {
64 this.fileManager = fm;
65 this.zdir = zdir;
66 this.map = new HashMap<RelativeDirectory,List<String>>();
67 if (initMap)
68 initMap();
69 }
71 protected void initMap() throws IOException {
72 for (Enumeration<? extends ZipEntry> e = zdir.entries(); e.hasMoreElements(); ) {
73 ZipEntry entry;
74 try {
75 entry = e.nextElement();
76 } catch (InternalError ex) {
77 IOException io = new IOException();
78 io.initCause(ex); // convenience constructors added in Mustang :-(
79 throw io;
80 }
81 addZipEntry(entry);
82 }
83 }
85 void addZipEntry(ZipEntry entry) {
86 String name = entry.getName();
87 int i = name.lastIndexOf('/');
88 RelativeDirectory dirname = new RelativeDirectory(name.substring(0, i+1));
89 String basename = name.substring(i+1);
90 if (basename.length() == 0)
91 return;
92 List<String> list = map.get(dirname);
93 if (list == null)
94 list = List.nil();
95 list = list.prepend(basename);
96 map.put(dirname, list);
97 }
99 public boolean contains(RelativePath name) {
100 RelativeDirectory dirname = name.dirname();
101 String basename = name.basename();
102 if (basename.length() == 0)
103 return false;
104 List<String> list = map.get(dirname);
105 return (list != null && list.contains(basename));
106 }
108 public List<String> getFiles(RelativeDirectory subdirectory) {
109 return map.get(subdirectory);
110 }
112 public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
113 ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zdir);
114 return new ZipFileObject(this, file, ze);
115 }
117 public Set<RelativeDirectory> getSubdirectories() {
118 return map.keySet();
119 }
121 public void close() throws IOException {
122 zdir.close();
123 }
125 @Override
126 public String toString() {
127 return "ZipArchive[" + zdir.getName() + "]";
128 }
130 protected JavacFileManager fileManager;
131 protected final Map<RelativeDirectory,List<String>> map;
132 protected final ZipFile zdir;
134 /**
135 * A subclass of JavaFileObject representing zip entries.
136 */
137 public static class ZipFileObject extends BaseFileObject {
139 private String name;
140 ZipArchive zarch;
141 ZipEntry entry;
143 protected ZipFileObject(ZipArchive zarch, String name, ZipEntry entry) {
144 super(zarch.fileManager);
145 this.zarch = zarch;
146 this.name = name;
147 this.entry = entry;
148 }
150 public URI toUri() {
151 File zipFile = new File(zarch.zdir.getName());
152 return createJarUri(zipFile, entry.getName());
153 }
155 @Override
156 public String getName() {
157 return zarch.zdir.getName() + "(" + entry.getName() + ")";
158 }
160 @Override
161 public String getShortName() {
162 return new File(zarch.zdir.getName()).getName() + "(" + entry + ")";
163 }
165 @Override
166 public JavaFileObject.Kind getKind() {
167 return getKind(entry.getName());
168 }
170 @Override
171 public InputStream openInputStream() throws IOException {
172 return zarch.zdir.getInputStream(entry);
173 }
175 @Override
176 public OutputStream openOutputStream() throws IOException {
177 throw new UnsupportedOperationException();
178 }
180 @Override
181 public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
182 CharBuffer cb = fileManager.getCachedContent(this);
183 if (cb == null) {
184 InputStream in = zarch.zdir.getInputStream(entry);
185 try {
186 ByteBuffer bb = fileManager.makeByteBuffer(in);
187 JavaFileObject prev = fileManager.log.useSource(this);
188 try {
189 cb = fileManager.decode(bb, ignoreEncodingErrors);
190 } finally {
191 fileManager.log.useSource(prev);
192 }
193 fileManager.recycleByteBuffer(bb);
194 if (!ignoreEncodingErrors) {
195 fileManager.cache(this, cb);
196 }
197 } finally {
198 in.close();
199 }
200 }
201 return cb;
202 }
204 @Override
205 public Writer openWriter() throws IOException {
206 throw new UnsupportedOperationException();
207 }
209 @Override
210 public long getLastModified() {
211 return entry.getTime();
212 }
214 @Override
215 public boolean delete() {
216 throw new UnsupportedOperationException();
217 }
219 @Override
220 protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
221 return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
222 }
224 @Override
225 protected String inferBinaryName(Iterable<? extends File> path) {
226 String entryName = entry.getName();
227 return removeExtension(entryName).replace('/', '.');
228 }
230 @Override
231 public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
232 cn.getClass();
233 // null check
234 if (k == Kind.OTHER && getKind() != k) {
235 return false;
236 }
237 return name.equals(cn + k.extension);
238 }
240 @Override
241 public boolean equals(Object other) {
242 if (!(other instanceof ZipFileObject)) {
243 return false;
244 }
245 ZipFileObject o = (ZipFileObject) other;
246 return zarch.zdir.equals(o.zarch.zdir) || name.equals(o.name);
247 }
249 @Override
250 public int hashCode() {
251 return zarch.zdir.hashCode() + name.hashCode();
252 }
253 }
255 }