001 /*
002 * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package com.sun.tools.javac.file;
027
028 import java.io.IOException;
029 import java.util.Set;
030 import javax.tools.JavaFileObject;
031
032 import java.io.ByteArrayInputStream;
033 import java.io.File;
034 import java.io.InputStream;
035 import java.io.OutputStream;
036 import java.io.Writer;
037 import java.net.URI;
038 import java.nio.ByteBuffer;
039 import java.nio.CharBuffer;
040 import java.nio.charset.CharsetDecoder;
041
042 import com.sun.tools.javac.file.JavacFileManager.Archive;
043 import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
044 import com.sun.tools.javac.file.RelativePath.RelativeFile;
045 import com.sun.tools.javac.util.List;
046
047 public class ZipFileIndexArchive implements Archive {
048
049 private final ZipFileIndex zfIndex;
050 private JavacFileManager fileManager;
051
052 public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException {
053 super();
054 this.fileManager = fileManager;
055 this.zfIndex = zdir;
056 }
057
058 public boolean contains(RelativePath name) {
059 return zfIndex.contains(name);
060 }
061
062 public List<String> getFiles(RelativeDirectory subdirectory) {
063 return zfIndex.getFiles(subdirectory);
064 }
065
066 public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) {
067 RelativeFile fullZipFileName = new RelativeFile(subdirectory, file);
068 ZipFileIndex.Entry entry = zfIndex.getZipIndexEntry(fullZipFileName);
069 JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile().getPath());
070 return ret;
071 }
072
073 public Set<RelativeDirectory> getSubdirectories() {
074 return zfIndex.getAllDirectories();
075 }
076
077 public void close() throws IOException {
078 zfIndex.close();
079 }
080
081 public String toString() {
082 return "ZipFileIndexArchive[" + zfIndex + "]";
083 }
084
085 /**
086 * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.file.ZipFileIndex implementation.
087 */
088 public static class ZipFileIndexFileObject extends BaseFileObject {
089
090 /** The entry's name.
091 */
092 private String name;
093
094 /** The zipfile containing the entry.
095 */
096 ZipFileIndex zfIndex;
097
098 /** The underlying zip entry object.
099 */
100 ZipFileIndex.Entry entry;
101
102 /** The InputStream for this zip entry (file.)
103 */
104 InputStream inputStream = null;
105
106 /** The name of the zip file where this entry resides.
107 */
108 String zipName;
109
110
111 ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, String zipFileName) {
112 super(fileManager);
113 this.name = entry.getFileName();
114 this.zfIndex = zfIndex;
115 this.entry = entry;
116 this.zipName = zipFileName;
117 }
118
119 public InputStream openInputStream() throws IOException {
120
121 if (inputStream == null) {
122 inputStream = new ByteArrayInputStream(read());
123 }
124 return inputStream;
125 }
126
127 protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) {
128 return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors);
129 }
130
131 public OutputStream openOutputStream() throws IOException {
132 throw new UnsupportedOperationException();
133 }
134
135 public Writer openWriter() throws IOException {
136 throw new UnsupportedOperationException();
137 }
138
139 /** @deprecated see bug 6410637 */
140 @Deprecated
141 public String getName() {
142 return name;
143 }
144
145 public boolean isNameCompatible(String cn, JavaFileObject.Kind k) {
146 cn.getClass(); // null check
147 if (k == Kind.OTHER && getKind() != k)
148 return false;
149 return name.equals(cn + k.extension);
150 }
151
152 /** @deprecated see bug 6410637 */
153 @Deprecated
154 public String getPath() {
155 return zipName + "(" + entry.getName() + ")";
156 }
157
158 public long getLastModified() {
159 return entry.getLastModified();
160 }
161
162 public boolean delete() {
163 throw new UnsupportedOperationException();
164 }
165
166 @Override
167 public boolean equals(Object other) {
168 if (!(other instanceof ZipFileIndexFileObject))
169 return false;
170 ZipFileIndexFileObject o = (ZipFileIndexFileObject) other;
171 return entry.equals(o.entry);
172 }
173
174 @Override
175 public int hashCode() {
176 return zipName.hashCode() + (name.hashCode() << 10);
177 }
178
179 public String getZipName() {
180 return zipName;
181 }
182
183 public String getZipEntryName() {
184 return entry.getName();
185 }
186
187 public URI toUri() {
188 String zipName = new File(getZipName()).toURI().normalize().getPath();
189 String entryName = getZipEntryName();
190 return URI.create("jar:" + zipName + "!" + entryName);
191 }
192
193 private byte[] read() throws IOException {
194 assert entry != null; // see constructor
195 return zfIndex.read(entry);
196 }
197
198 public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException {
199 CharBuffer cb = fileManager.getCachedContent(this);
200 if (cb == null) {
201 InputStream in = new ByteArrayInputStream(zfIndex.read(entry));
202 try {
203 ByteBuffer bb = fileManager.makeByteBuffer(in);
204 JavaFileObject prev = fileManager.log.useSource(this);
205 try {
206 cb = fileManager.decode(bb, ignoreEncodingErrors);
207 } finally {
208 fileManager.log.useSource(prev);
209 }
210 fileManager.recycleByteBuffer(bb); // save for next time
211 if (!ignoreEncodingErrors)
212 fileManager.cache(this, cb);
213 } finally {
214 in.close();
215 }
216 }
217 return cb;
218 }
219
220 @Override
221 protected String inferBinaryName(Iterable<? extends File> path) {
222 String entryName = getZipEntryName();
223 if (zfIndex.symbolFilePrefix != null) {
224 String prefix = zfIndex.symbolFilePrefix.path;
225 if (entryName.startsWith(prefix))
226 entryName = entryName.substring(prefix.length());
227 }
228 return removeExtension(entryName).replace('/', '.');
229 }
230 }
231
232 }