001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.java.source.parsing;
043:
044: import java.beans.PropertyChangeEvent;
045: import java.beans.PropertyChangeListener;
046: import java.io.IOException;
047: import java.net.URL;
048: import java.util.ArrayList;
049: import java.util.Iterator;
050: import java.util.LinkedList;
051: import java.util.List;
052: import java.util.Set;
053: import java.util.logging.Level;
054: import java.util.logging.Logger;
055: import javax.tools.FileObject;
056: import javax.tools.JavaFileManager;
057: import javax.tools.JavaFileObject;
058: import org.netbeans.api.java.classpath.ClassPath;
059: import org.netbeans.modules.java.preprocessorbridge.spi.JavaFileFilterImplementation;
060: import org.netbeans.modules.java.source.classpath.CacheClassPath;
061: import org.netbeans.modules.java.source.util.Iterators;
062: import org.openide.filesystems.FileUtil;
063: import org.openide.util.Exceptions;
064: import org.openide.util.WeakListeners;
065:
066: /** Implementation of file manager for given classpath.
067: *
068: * @author Petr Hrebejk
069: */
070: public class CachingFileManager implements JavaFileManager,
071: PropertyChangeListener {
072:
073: protected final CachingArchiveProvider provider;
074: protected final JavaFileFilterImplementation filter;
075: protected final ClassPath cp;
076: protected final boolean cacheFile;
077: protected final boolean ignoreExcludes;
078:
079: private static final Logger LOG = Logger
080: .getLogger(CachingFileManager.class.getName());
081:
082: public CachingFileManager(CachingArchiveProvider provider,
083: final ClassPath cp, boolean cacheFile,
084: boolean ignoreExcludes) {
085: this (provider, cp, null, cacheFile, ignoreExcludes);
086: }
087:
088: /** Creates a new instance of CachingFileManager */
089: public CachingFileManager(CachingArchiveProvider provider,
090: final ClassPath cp,
091: final JavaFileFilterImplementation filter,
092: boolean cacheFile, boolean ignoreExcludes) {
093: this .provider = provider;
094: this .cp = cp;
095: if (CacheClassPath.KEEP_JARS) {
096: cp.addPropertyChangeListener(WeakListeners.propertyChange(
097: this , cp));
098: }
099: this .cacheFile = cacheFile;
100: this .filter = filter;
101: this .ignoreExcludes = ignoreExcludes;
102: }
103:
104: // FileManager implementation ----------------------------------------------
105:
106: // XXX omit files not of given kind
107: public Iterable<JavaFileObject> list(Location l,
108: String packageName, Set<JavaFileObject.Kind> kinds,
109: boolean recursive) {
110:
111: if (recursive) {
112: throw new UnsupportedOperationException(
113: "Recursive listing is not supported in archives");
114: }
115:
116: // long start = System.currentTimeMillis();
117:
118: String folderName = FileObjects
119: .convertPackage2Folder(packageName);
120:
121: List<Iterable<JavaFileObject>> idxs = new LinkedList<Iterable<JavaFileObject>>();
122: for (ClassPath.Entry entry : this .cp.entries()) {
123: try {
124: Archive archive = provider.getArchive(entry.getURL(),
125: cacheFile);
126: if (archive != null) {
127: Iterable<JavaFileObject> entries = archive
128: .getFiles(folderName, ignoreExcludes ? null
129: : entry, kinds, filter);
130: idxs.add(entries);
131: if (LOG.isLoggable(Level.FINEST)) {
132: final StringBuilder urls = new StringBuilder();
133: for (JavaFileObject jfo : entries) {
134: urls.append(jfo.toUri().toString());
135: urls.append(", "); //NOI18N
136: }
137: LOG
138: .finest(String
139: .format(
140: "cache for %s (%s) package: %s type: %s files: [%s]", //NOI18N
141: l.toString(),
142: entry
143: .getURL()
144: .toExternalForm(),
145: packageName, kinds
146: .toString(),
147: urls.toString()));
148: }
149: } else if (LOG.isLoggable(Level.FINEST)) {
150: LOG.finest(String.format("no cache for: %s", entry
151: .getURL().toExternalForm())); //NOI18N
152: }
153: } catch (IOException e) {
154: Exceptions.printStackTrace(e);
155: }
156: }
157: return Iterators.chained(idxs);
158: }
159:
160: public javax.tools.FileObject getFileForInput(Location l,
161: String pkgName, String relativeName) {
162:
163: for (ClassPath.Entry root : this .cp.entries()) {
164: try {
165: Archive archive = provider.getArchive(root.getURL(),
166: cacheFile);
167: if (archive != null) {
168: Iterable<JavaFileObject> files = archive.getFiles(
169: FileObjects.convertPackage2Folder(pkgName),
170: ignoreExcludes ? null : root, null, filter);
171: for (JavaFileObject e : files) {
172: if (relativeName.equals(e.getName())) {
173: return e;
174: }
175: }
176: }
177: } catch (IOException e) {
178: Exceptions.printStackTrace(e);
179: }
180: }
181: return null;
182: }
183:
184: public JavaFileObject getJavaFileForInput(Location l,
185: String className, JavaFileObject.Kind kind) {
186: String[] namePair = FileObjects
187: .getParentRelativePathAndName(className);
188: if (namePair == null) {
189: return null;
190: }
191: namePair[1] = namePair[1] + kind.extension;
192: for (ClassPath.Entry root : this .cp.entries()) {
193: try {
194: Archive archive = provider.getArchive(root.getURL(),
195: cacheFile);
196: if (archive != null) {
197: Iterable<JavaFileObject> files = archive.getFiles(
198: namePair[0], ignoreExcludes ? null : root,
199: null, filter);
200: for (JavaFileObject e : files) {
201: if (namePair[1].equals(e.getName())) {
202: return e;
203: }
204: }
205: }
206: } catch (IOException e) {
207: Exceptions.printStackTrace(e);
208: }
209: }
210: return null;
211: }
212:
213: public javax.tools.FileObject getFileForOutput(Location l,
214: String pkgName, String relativeName,
215: javax.tools.FileObject sibling) throws IOException,
216: UnsupportedOperationException, IllegalArgumentException {
217: throw new UnsupportedOperationException();
218: }
219:
220: public JavaFileObject getJavaFileForOutput(Location l,
221: String className, JavaFileObject.Kind kind,
222: javax.tools.FileObject sibling) throws IOException,
223: UnsupportedOperationException, IllegalArgumentException {
224: throw new UnsupportedOperationException();
225: }
226:
227: public void flush() throws IOException {
228: // XXX Do nothing?
229: }
230:
231: public void close() throws IOException {
232: // XXX Do nothing?
233: }
234:
235: public int isSupportedOption(String string) {
236: return -1;
237: }
238:
239: public boolean handleOption(final String head,
240: final Iterator<String> tail) {
241: return false;
242: }
243:
244: public boolean hasLocation(Location location) {
245: return true;
246: }
247:
248: public ClassLoader getClassLoader(final Location l) {
249: return null;
250: }
251:
252: public String inferBinaryName(Location l,
253: JavaFileObject javaFileObject) {
254: if (javaFileObject instanceof FileObjects.Base) {
255: final FileObjects.Base base = (FileObjects.Base) javaFileObject;
256: final StringBuilder sb = new StringBuilder();
257: sb.append(base.getPackage());
258: sb.append('.'); //NOI18N
259: sb.append(base.getNameWithoutExtension());
260: return sb.toString();
261: } else if (javaFileObject instanceof SourceFileObject) {
262: org.openide.filesystems.FileObject fo = ((SourceFileObject) javaFileObject).file;
263: for (org.openide.filesystems.FileObject root : this .cp
264: .getRoots()) {
265: if (FileUtil.isParentOf(root, fo)) {
266: String relativePath = FileUtil.getRelativePath(
267: root, fo);
268: int index = relativePath.lastIndexOf('.'); //NOI18N
269: assert index > 0;
270: final String result = relativePath.substring(0,
271: index).replace('/', '.'); //NOI18N
272: return result;
273: }
274: }
275: }
276: return null;
277: }
278:
279: //Static helpers - temporary
280:
281: public static URL[] getClassPathRoots(final ClassPath cp) {
282: assert cp != null;
283: final List<ClassPath.Entry> entries = cp.entries();
284: final List<URL> result = new ArrayList<URL>(entries.size());
285: for (ClassPath.Entry entry : entries) {
286: result.add(entry.getURL());
287: }
288: return result.toArray(new URL[result.size()]);
289: }
290:
291: public boolean isSameFile(FileObject fileObject,
292: FileObject fileObject0) {
293: return fileObject instanceof FileObjects.FileBase
294: && fileObject0 instanceof FileObjects.FileBase
295: && ((FileObjects.FileBase) fileObject).getFile()
296: .equals(
297: ((FileObjects.FileBase) fileObject)
298: .getFile());
299: }
300:
301: public void propertyChange(PropertyChangeEvent evt) {
302: if (ClassPath.PROP_ROOTS.equals(evt.getPropertyName())) {
303: provider.clear();
304: }
305: }
306: }
|