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 10:00:08 +0200 (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 }