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.xbean.osgi.bundle.util.jar;
018
019 import java.io.File;
020 import java.io.FileOutputStream;
021 import java.io.IOException;
022 import java.io.InputStream;
023 import java.net.URL;
024 import java.util.Collections;
025 import java.util.Enumeration;
026 import java.util.LinkedList;
027 import java.util.jar.JarEntry;
028 import java.util.jar.JarFile;
029 import java.util.jar.JarOutputStream;
030 import java.util.jar.Manifest;
031 import java.util.zip.ZipEntry;
032
033 import org.osgi.framework.Bundle;
034
035 /**
036 * @version $Rev: 937957 $ $Date: 2010-04-26 16:00:08 +0800 (Mon, 26 Apr 2010) $
037 */
038 public class BundleJarFile extends JarFile {
039
040 private static final File DUMMY_JAR_FILE;
041
042 static {
043 try {
044 DUMMY_JAR_FILE = createTempFile();
045 new JarOutputStream(new FileOutputStream(BundleJarFile.DUMMY_JAR_FILE), new Manifest()).close();
046 } catch (IOException e) {
047 throw new ExceptionInInitializerError(e);
048 }
049 }
050 private final Bundle bundle;
051 private boolean manifestLoaded = false;
052 private Manifest manifest;
053
054 public BundleJarFile(Bundle bundle) throws IOException {
055 super(DUMMY_JAR_FILE);
056 this.bundle = bundle;
057 }
058
059 public Bundle getBundle() {
060 return bundle;
061 }
062
063 public Manifest getManifest() throws IOException {
064 if (!manifestLoaded) {
065 URL manifestURL = bundle.getEntry("META-INF/MANIFEST.MF");
066 if (manifestURL != null) {
067 InputStream in = null;
068 try {
069 in = manifestURL.openStream();
070 manifest = new Manifest(in);
071 } finally {
072 if (in != null) {
073 try {
074 in.close();
075 } catch (IOException e) {
076 // ignore
077 }
078 }
079 }
080 }
081 manifestLoaded = true;
082 }
083 return manifest;
084 }
085
086 public BundleJarEntry getBundleJarEntry(String name) {
087 URL url = bundle.getEntry(name);
088 if (url == null) {
089 return null;
090 }
091 return new BundleJarEntry(name, url, getManifestSafe());
092 }
093
094 public JarEntry getJarEntry(String name) {
095 return getBundleJarEntry(name);
096 }
097
098 public ZipEntry getEntry(String name) {
099 return getBundleJarEntry(name);
100 }
101
102 public Enumeration entries() {
103 Manifest manifest = getManifestSafe();
104 Enumeration e = bundle.findEntries("/", "*", true);
105 LinkedList entries = new LinkedList();
106 while (e.hasMoreElements()) {
107 URL entryURL = (URL) e.nextElement();
108 entries.add(new BundleJarEntry(entryURL.getPath(), entryURL, manifest));
109 }
110 return Collections.enumeration(entries);
111 }
112
113 public InputStream getInputStream(ZipEntry zipEntry) throws IOException {
114 BundleJarEntry entry;
115 if (zipEntry instanceof BundleJarEntry) {
116 entry = (BundleJarEntry) zipEntry;
117 } else {
118 entry = getBundleJarEntry(zipEntry.getName());
119 }
120
121 if (entry == null) {
122 throw new IOException("Entry not found: name=" + zipEntry.getName());
123 } else if (entry.isDirectory()) {
124 return new EmptyInputStream();
125 } else {
126 return entry.getEntryURL().openStream();
127 }
128 }
129
130 public String getName() {
131 return bundle.getSymbolicName();
132 }
133
134 public int size() {
135 return -1;
136 }
137
138 public void close() throws IOException {
139 }
140
141 private Manifest getManifestSafe() {
142 Manifest manifest = null;
143 try {
144 manifest = getManifest();
145 } catch (IOException e) {
146 // ignore
147 }
148 return manifest;
149 }
150
151 // be careful to clean up the temp file... we tell the vm to delete this on exit
152 // but VMs can't be trusted to acutally delete the file
153 private static File createTempFile() throws IOException {
154 File tempFile = File.createTempFile("geronimo-fileutils", ".tmpfile");
155 tempFile.deleteOnExit();
156 return tempFile;
157 }
158
159
160 private static final class EmptyInputStream extends InputStream {
161
162 public int read() {
163 return -1;
164 }
165
166 public int read(byte b[]) {
167 return -1;
168 }
169
170 public int read(byte b[], int off, int len) {
171 return -1;
172 }
173
174 public long skip(long n) {
175 return 0;
176 }
177
178 public int available() {
179 return 0;
180 }
181
182 public void close() {
183 }
184
185 public synchronized void mark(int readlimit) {
186 }
187
188 public synchronized void reset() {
189 }
190
191 public boolean markSupported() {
192 return false;
193 }
194 }
195
196 }