001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2006, University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.classfile.impl;
021:
022: import java.io.BufferedOutputStream;
023: import java.io.File;
024: import java.io.FileOutputStream;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.io.OutputStream;
028:
029: import edu.umd.cs.findbugs.ba.AnalysisContext;
030: import edu.umd.cs.findbugs.classfile.ICodeBase;
031: import edu.umd.cs.findbugs.classfile.ICodeBaseEntry;
032: import edu.umd.cs.findbugs.classfile.ICodeBaseIterator;
033: import edu.umd.cs.findbugs.classfile.IScannableCodeBase;
034: import edu.umd.cs.findbugs.classfile.ResourceNotFoundException;
035: import edu.umd.cs.findbugs.io.IO;
036:
037: /**
038: * A scannable code base class for a zip (or Jar) file nested inside
039: * some other codebase. These are handled by extracting the nested
040: * zip/jar file to a temporary file, and delegating to an
041: * internal ZipFileCodeBase that reads from the temporary file.
042: *
043: * @author David Hovemeyer
044: */
045: public class NestedZipFileCodeBase extends AbstractScannableCodeBase
046: implements IScannableCodeBase {
047: private ICodeBase parentCodeBase;
048: private String resourceName;
049: private File tempFile;
050: private AbstractScannableCodeBase delegateCodeBase;
051:
052: /**
053: * Constructor.
054: *
055: * @param codeBaseLocator the codebase locator for this codebase
056: */
057: public NestedZipFileCodeBase(
058: NestedZipFileCodeBaseLocator codeBaseLocator)
059: throws ResourceNotFoundException, IOException {
060: super (codeBaseLocator);
061: this .parentCodeBase = codeBaseLocator.getParentCodeBase();
062: this .resourceName = codeBaseLocator.getResourceName();
063:
064: InputStream inputStream = null;
065: OutputStream outputStream = null;
066: try {
067: // Create a temp file
068: this .tempFile = File.createTempFile("findbugs", ".zip");
069: tempFile.deleteOnExit(); // just in case we crash before the codebase is closed
070:
071: // Copy nested zipfile to the temporary file
072: // FIXME: potentially long blocking operation - should be interruptible
073: ICodeBaseEntry resource = parentCodeBase
074: .lookupResource(resourceName);
075: if (resource == null) {
076: return;
077: }
078: inputStream = resource.openResource();
079: outputStream = new BufferedOutputStream(
080: new FileOutputStream(tempFile));
081: IO.copy(inputStream, outputStream);
082: outputStream.flush();
083:
084: // Create the delegate to read from the temporary file
085: delegateCodeBase = ZipCodeBaseFactory.makeZipCodeBase(
086: codeBaseLocator, tempFile);
087: } finally {
088: if (inputStream != null) {
089: IO.close(inputStream);
090: }
091:
092: if (outputStream != null) {
093: IO.close(outputStream);
094: }
095: }
096: }
097:
098: /* (non-Javadoc)
099: * @see edu.umd.cs.findbugs.classfile.IScannableCodeBase#iterator()
100: */
101: public ICodeBaseIterator iterator() throws InterruptedException {
102: return new DelegatingCodeBaseIterator(this , delegateCodeBase);
103: }
104:
105: /* (non-Javadoc)
106: * @see edu.umd.cs.findbugs.classfile.ICodeBase#lookupResource(java.lang.String)
107: */
108: public ICodeBaseEntry lookupResource(String resourceName) {
109: ICodeBaseEntry delegateCodeBaseEntry = delegateCodeBase
110: .lookupResource(resourceName);
111: if (delegateCodeBaseEntry == null) {
112: return null;
113: }
114: return new DelegatingCodeBaseEntry(this , delegateCodeBaseEntry);
115: }
116:
117: /* (non-Javadoc)
118: * @see edu.umd.cs.findbugs.classfile.ICodeBase#getPathName()
119: */
120: public String getPathName() {
121: return null;
122: }
123:
124: /* (non-Javadoc)
125: * @see edu.umd.cs.findbugs.classfile.ICodeBase#close()
126: */
127: public void close() {
128: delegateCodeBase.close();
129: if (!tempFile.delete()) {
130: AnalysisContext.logError("Could not delete " + tempFile);
131: }
132: }
133: }
|