001: /*******************************************************************************
002: * Copyright (c) 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.tool;
011:
012: import java.io.File;
013: import java.io.IOException;
014: import java.io.InputStream;
015: import java.io.OutputStream;
016: import java.io.Reader;
017: import java.io.Writer;
018: import java.net.URI;
019: import java.net.URISyntaxException;
020: import java.nio.charset.Charset;
021: import java.util.zip.ZipEntry;
022: import java.util.zip.ZipFile;
023:
024: import javax.lang.model.element.Modifier;
025: import javax.lang.model.element.NestingKind;
026: import javax.tools.JavaFileObject;
027:
028: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
029: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
030: import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
031:
032: /**
033: * Implementation of a Java file object that corresponds to an entry in a zip/jar file
034: */
035: public class ArchiveFileObject implements JavaFileObject {
036: private ZipEntry zipEntry;
037: private ZipFile zipFile;
038: private String entryName;
039: private File file;
040: private Charset charset;
041:
042: public ArchiveFileObject(File file, ZipFile zipFile,
043: String entryName, Charset charset) {
044: this .zipFile = zipFile;
045: this .zipEntry = zipFile.getEntry(entryName);
046: this .entryName = entryName;
047: this .file = file;
048: this .charset = charset;
049: }
050:
051: /* (non-Javadoc)
052: * @see javax.tools.JavaFileObject#getAccessLevel()
053: */
054: public Modifier getAccessLevel() {
055: // cannot express multiple modifier
056: if (getKind() != Kind.CLASS) {
057: return null;
058: }
059: ClassFileReader reader = null;
060: try {
061: reader = ClassFileReader.read(this .zipFile, this .entryName);
062: } catch (ClassFormatException e) {
063: // ignore
064: } catch (IOException e) {
065: // ignore
066: }
067: if (reader == null) {
068: return null;
069: }
070: final int accessFlags = reader.accessFlags();
071: if ((accessFlags & ClassFileConstants.AccPublic) != 0) {
072: return Modifier.PUBLIC;
073: }
074: if ((accessFlags & ClassFileConstants.AccAbstract) != 0) {
075: return Modifier.ABSTRACT;
076: }
077: if ((accessFlags & ClassFileConstants.AccFinal) != 0) {
078: return Modifier.FINAL;
079: }
080: return null;
081: }
082:
083: /* (non-Javadoc)
084: * @see javax.tools.JavaFileObject#getKind()
085: */
086: public Kind getKind() {
087: String name = this .entryName.toLowerCase();
088: if (name.endsWith(Kind.CLASS.extension)) {
089: return Kind.CLASS;
090: } else if (name.endsWith(Kind.SOURCE.extension)) {
091: return Kind.SOURCE;
092: } else if (name.endsWith(Kind.HTML.extension)) {
093: return Kind.HTML;
094: }
095: return Kind.OTHER;
096: }
097:
098: /* (non-Javadoc)
099: * @see javax.tools.JavaFileObject#getNestingKind()
100: */
101: public NestingKind getNestingKind() {
102: switch (getKind()) {
103: case SOURCE:
104: return NestingKind.TOP_LEVEL;
105: case CLASS:
106: ClassFileReader reader = null;
107: try {
108: reader = ClassFileReader.read(this .zipFile,
109: this .entryName);
110: } catch (ClassFormatException e) {
111: // ignore
112: } catch (IOException e) {
113: // ignore
114: }
115: if (reader == null) {
116: return null;
117: }
118: if (reader.isAnonymous()) {
119: return NestingKind.ANONYMOUS;
120: }
121: if (reader.isLocal()) {
122: return NestingKind.LOCAL;
123: }
124: if (reader.isMember()) {
125: return NestingKind.MEMBER;
126: }
127: return NestingKind.TOP_LEVEL;
128: default:
129: return null;
130: }
131: }
132:
133: /* (non-Javadoc)
134: * @see javax.tools.JavaFileObject#isNameCompatible(java.lang.String, javax.tools.JavaFileObject.Kind)
135: */
136: public boolean isNameCompatible(String simpleName, Kind kind) {
137: return this .zipEntry.getName().endsWith(
138: simpleName + kind.extension);
139: }
140:
141: /* (non-Javadoc)
142: * @see javax.tools.FileObject#delete()
143: */
144: public boolean delete() {
145: throw new UnsupportedOperationException();
146: }
147:
148: public boolean equals(Object o) {
149: if (!(o instanceof ArchiveFileObject)) {
150: return false;
151: }
152: ArchiveFileObject archiveFileObject = (ArchiveFileObject) o;
153: return archiveFileObject.toUri().equals(this .toUri());
154: }
155:
156: /* (non-Javadoc)
157: * @see javax.tools.FileObject#getCharContent(boolean)
158: */
159: public CharSequence getCharContent(boolean ignoreEncodingErrors)
160: throws IOException {
161: if (getKind() == Kind.SOURCE) {
162: return Util.getCharContents(this , ignoreEncodingErrors,
163: org.eclipse.jdt.internal.compiler.util.Util
164: .getZipEntryByteContent(this .zipEntry,
165: this .zipFile), this .charset
166: .toString());
167: }
168: return null;
169: }
170:
171: /* (non-Javadoc)
172: * @see javax.tools.FileObject#getLastModified()
173: */
174: public long getLastModified() {
175: return this .zipEntry.getTime(); // looks the closest from the last modification
176: }
177:
178: /* (non-Javadoc)
179: * @see javax.tools.FileObject#getName()
180: */
181: public String getName() {
182: return this .zipEntry.getName();
183: }
184:
185: /* (non-Javadoc)
186: * @see javax.tools.FileObject#openInputStream()
187: */
188: public InputStream openInputStream() throws IOException {
189: return this .zipFile.getInputStream(this .zipEntry);
190: }
191:
192: /* (non-Javadoc)
193: * @see javax.tools.FileObject#openOutputStream()
194: */
195: public OutputStream openOutputStream() throws IOException {
196: throw new UnsupportedOperationException();
197: }
198:
199: /* (non-Javadoc)
200: * @see javax.tools.FileObject#openReader(boolean)
201: */
202: public Reader openReader(boolean ignoreEncodingErrors)
203: throws IOException {
204: throw new UnsupportedOperationException();
205: }
206:
207: /* (non-Javadoc)
208: * @see javax.tools.FileObject#openWriter()
209: */
210: public Writer openWriter() throws IOException {
211: throw new UnsupportedOperationException();
212: }
213:
214: /* (non-Javadoc)
215: * @see javax.tools.FileObject#toUri()
216: */
217: public URI toUri() {
218: try {
219: return new URI(
220: "jar:" + this .file.toURI().getPath() + "!" + this .zipEntry.getName()); //$NON-NLS-1$//$NON-NLS-2$
221: } catch (URISyntaxException e) {
222: return null;
223: }
224: }
225:
226: @Override
227: public String toString() {
228: return this .file.getAbsolutePath()
229: + "[" + this .zipEntry.getName() + "]";//$NON-NLS-1$//$NON-NLS-2$
230: }
231: }
|