001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.source.impl;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.ByteArrayOutputStream;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.util.zip.ZipEntry;
024: import java.util.zip.ZipInputStream;
025:
026: import org.apache.avalon.framework.logger.AbstractLogEnabled;
027: import org.apache.cocoon.util.MIMEUtils;
028: import org.apache.excalibur.source.Source;
029: import org.apache.excalibur.source.SourceNotFoundException;
030: import org.apache.excalibur.source.SourceValidity;
031: import org.apache.excalibur.source.SourceResolver;
032:
033: /**
034: * @author <a href="http://apache.org/~reinhard">Reinhard Poetz</a>
035: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
036: * @version CVS $Id: ZipSource.java 517444 2007-03-12 22:49:37Z joerg $
037: * @since 2.1.8
038: */
039: public class ZipSource extends AbstractLogEnabled implements Source {
040:
041: private String protocol;
042: private Source archive;
043: private String filePath;
044:
045: public ZipSource(String protocol, Source archive, String filePath) {
046: this .protocol = protocol;
047: this .archive = archive;
048: this .filePath = filePath;
049: }
050:
051: private ZipEntry findEntry(ZipInputStream zipStream)
052: throws IOException {
053: ZipEntry entry;
054: while ((entry = zipStream.getNextEntry()) != null) {
055: if (entry.getName().equals(this .filePath)) {
056: return entry;
057: }
058: zipStream.closeEntry();
059: }
060:
061: return null;
062: }
063:
064: /* package access */
065: void dispose(SourceResolver resolver) {
066: resolver.release(this .archive);
067: this .archive = null;
068: }
069:
070: public boolean exists() {
071: if (!this .archive.exists()) {
072: return false;
073: }
074:
075: ZipInputStream zipStream = null;
076: try {
077: zipStream = new ZipInputStream(this .archive
078: .getInputStream());
079: return findEntry(zipStream) != null;
080: } catch (IOException e) {
081: return false;
082: } finally {
083: try {
084: if (zipStream != null) {
085: zipStream.close();
086: }
087: } catch (IOException e) {
088: getLogger().error(
089: "IOException while closing ZipInputStream: "
090: + this .filePath);
091: }
092: }
093: }
094:
095: public InputStream getInputStream() throws IOException,
096: SourceNotFoundException {
097: ZipInputStream zipStream = new ZipInputStream(this .archive
098: .getInputStream());
099: try {
100: ZipEntry entry = findEntry(zipStream);
101: if (entry == null) {
102: throw new SourceNotFoundException("File "
103: + this .filePath
104: + " is not found in the archive "
105: + this .archive.getURI());
106: }
107:
108: // Now we will extract the document and write it into a byte array
109: ByteArrayOutputStream baos = new ByteArrayOutputStream();
110: byte[] buffer = new byte[8192];
111: int length;
112: while (zipStream.available() > 0) {
113: length = zipStream.read(buffer, 0, 8192);
114: if (length > 0) {
115: baos.write(buffer, 0, length);
116: }
117: }
118:
119: // Return an input stream
120: return new ByteArrayInputStream(baos.toByteArray());
121: } finally {
122: try {
123: zipStream.close();
124: } catch (IOException e) {
125: getLogger().error(
126: "IOException while closing ZipInputStream: "
127: + this .filePath);
128: }
129: }
130: }
131:
132: public String getURI() {
133: return this .protocol + ":" + this .archive.getURI() + "!/"
134: + this .filePath;
135: }
136:
137: public String getScheme() {
138: return this .protocol;
139: }
140:
141: public SourceValidity getValidity() {
142: return this .archive.getValidity();
143: }
144:
145: public void refresh() {
146: }
147:
148: public String getMimeType() {
149: String ext = this .filePath.substring(this .filePath
150: .lastIndexOf("."));
151: return MIMEUtils.getMIMEType(ext);
152: }
153:
154: public long getContentLength() {
155: ZipInputStream zipStream = null;
156: try {
157: zipStream = new ZipInputStream(this .archive
158: .getInputStream());
159: ZipEntry entry = findEntry(zipStream);
160: if (entry != null) {
161: return entry.getSize();
162: }
163:
164: } catch (IOException e) {
165: // Ignored
166: } finally {
167: try {
168: if (zipStream != null) {
169: zipStream.close();
170: }
171: } catch (IOException e) {
172: getLogger().error(
173: "IOException while closing ZipInputStream: "
174: + this .filePath);
175: }
176: }
177:
178: return -1;
179: }
180:
181: public long getLastModified() {
182: return this.archive.getLastModified();
183: }
184:
185: }
|