1 /**
2 *
3 * Copyright 2004 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.geronimo.deployment.util;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Enumeration;
25 import java.util.Iterator;
26 import java.util.LinkedList;
27 import java.util.jar.JarEntry;
28 import java.util.jar.JarFile;
29 import java.util.jar.Manifest;
30 import java.util.zip.ZipEntry;
31
32 /**
33 * @version $Rev: 394960 $ $Date: 2006-04-18 08:02:36 -0700 (Tue, 18 Apr 2006) $
34 */
35 public class NestedJarFile extends JarFile {
36 private JarFile baseJar;
37 private String basePath;
38 private boolean isClosed = false;
39 private boolean manifestLoaded = false;
40 private Manifest manifest;
41 private File tempFile;
42
43 public NestedJarFile(JarFile jarFile, String path) throws IOException {
44 super(DeploymentUtil.DUMMY_JAR_FILE);
45
46
47 JarEntry targetEntry = jarFile.getJarEntry(path + "/");
48 if (targetEntry == null) {
49 targetEntry = jarFile.getJarEntry(path);
50 if (targetEntry == null) {
51 throw new IOException("Jar entry does not exist: jarFile=" + jarFile.getName() + ", path=" + path);
52 }
53 }
54
55 if (targetEntry.isDirectory()) {
56 baseJar = jarFile;
57 if (!path.endsWith("/")) {
58 path += "/";
59 }
60 basePath = path;
61 } else {
62 if (targetEntry instanceof UnpackedJarEntry) {
63
64
65
66 File targetFile = ((UnpackedJarEntry) targetEntry).getFile();
67 baseJar = new JarFile(targetFile);
68 basePath = "";
69 } else {
70 tempFile = DeploymentUtil.toFile(jarFile, targetEntry.getName());
71 baseJar = new JarFile(tempFile);
72 basePath = "";
73 }
74 }
75 }
76
77 public boolean isUnpacked() {
78 if (isClosed) {
79 throw new IllegalStateException("NestedJarFile is closed");
80 }
81 return basePath.length() > 0;
82 }
83
84 public boolean isPacked() {
85 if (isClosed) {
86 throw new IllegalStateException("NestedJarFile is closed");
87 }
88 return basePath.length() == 0;
89 }
90
91 public JarFile getBaseJar() {
92 if (isClosed) {
93 throw new IllegalStateException("NestedJarFile is closed");
94 }
95 return baseJar;
96 }
97
98 public String getBasePath() {
99 if (isClosed) {
100 throw new IllegalStateException("NestedJarFile is closed");
101 }
102 return basePath;
103 }
104
105 public Manifest getManifest() throws IOException {
106 if (isClosed) {
107 throw new IllegalStateException("NestedJarFile is closed");
108 }
109
110 if (!manifestLoaded) {
111 JarEntry manifestEntry = getBaseEntry("META-INF/MANIFEST.MF");
112
113 if (manifestEntry != null && !manifestEntry.isDirectory()) {
114 InputStream in = null;
115 try {
116 in = baseJar.getInputStream(manifestEntry);
117 manifest = new Manifest(in);
118 } finally {
119 if (in != null) {
120 try {
121 in.close();
122 } catch (IOException e) {
123
124 }
125 }
126 }
127 }
128 manifestLoaded = true;
129 }
130 return manifest;
131 }
132
133 public NestedJarEntry getNestedJarEntry(String name) {
134 if (isClosed) {
135 throw new IllegalStateException("NestedJarFile is closed");
136 }
137
138 JarEntry baseEntry = getBaseEntry(name);
139 if (baseEntry == null) {
140 return null;
141 }
142 return new NestedJarEntry(name, baseEntry, getManifestSafe());
143 }
144
145 public JarEntry getJarEntry(String name) {
146 if (isClosed) {
147 throw new IllegalStateException("NestedJarFile is closed");
148 }
149
150 return getNestedJarEntry(name);
151 }
152
153 public ZipEntry getEntry(String name) {
154 if (isClosed) {
155 throw new IllegalStateException("NestedJarFile is closed");
156 }
157
158 return getNestedJarEntry(name);
159 }
160
161 public Enumeration entries() {
162 if (isClosed) {
163 throw new IllegalStateException("NestedJarFile is closed");
164 }
165
166 Collection baseEntries = Collections.list(baseJar.entries());
167 Collection entries = new LinkedList();
168 for (Iterator iterator = baseEntries.iterator(); iterator.hasNext();) {
169 JarEntry baseEntry = (JarEntry) iterator.next();
170 String path = baseEntry.getName();
171 if (path.startsWith(basePath)) {
172 entries.add(new NestedJarEntry(path.substring(basePath.length()), baseEntry, getManifestSafe()));
173 }
174 }
175 return Collections.enumeration(entries);
176 }
177
178 public InputStream getInputStream(ZipEntry zipEntry) throws IOException {
179 if (isClosed) {
180 throw new IllegalStateException("NestedJarFile is closed");
181 }
182
183 JarEntry baseEntry;
184 if (zipEntry instanceof NestedJarEntry) {
185 baseEntry = ((NestedJarEntry)zipEntry).getBaseEntry();
186 } else {
187 baseEntry = getBaseEntry(zipEntry.getName());
188 }
189
190 if (baseEntry == null) {
191 throw new IOException("Entry not found: name=" + baseEntry.getName());
192 } else if (baseEntry.isDirectory()) {
193 return new DeploymentUtil.EmptyInputStream();
194 }
195 return baseJar.getInputStream(baseEntry);
196 }
197
198 public String getName() {
199 return baseJar.getName();
200 }
201
202 /**
203 * Always returns -1.
204 * @return -1
205 */
206 public int size() {
207 if (isClosed) {
208 throw new IllegalStateException("NestedJarFile is closed");
209 }
210 return -1;
211 }
212
213 public void close() throws IOException {
214 if (isClosed) {
215 return;
216 }
217
218 try {
219 if (baseJar != null && isPacked()) {
220 baseJar.close();
221 }
222 } finally {
223 isClosed = true;
224 baseJar = null;
225 basePath = null;
226 manifestLoaded = false;
227 manifest = null;
228 if (tempFile != null) {
229 tempFile.delete();
230 tempFile = null;
231 }
232 }
233 }
234
235 protected void finalize() throws IOException {
236 close();
237 }
238
239 private JarEntry getBaseEntry(String name) {
240 return baseJar.getJarEntry(basePath + name);
241 }
242
243 private Manifest getManifestSafe() {
244 Manifest manifest = null;
245 try {
246 manifest = getManifest();
247 } catch (IOException e) {
248
249 }
250 return manifest;
251 }
252
253 }