KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > baseadaptor > bundlefile > ZipBundleFile


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.baseadaptor.bundlefile;
13
14 import java.io.*;
15 import java.util.*;
16 import java.util.zip.ZipEntry JavaDoc;
17 import java.util.zip.ZipFile JavaDoc;
18 import org.eclipse.osgi.baseadaptor.BaseData;
19 import org.eclipse.osgi.framework.debug.Debug;
20 import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
21 import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
22 import org.eclipse.osgi.util.NLS;
23 import org.osgi.framework.FrameworkEvent;
24
25 /**
26  * A BundleFile that uses a ZipFile as it base file.
27  * @since 3.2
28  */

29 public class ZipBundleFile extends BundleFile {
30     protected static MRUBundleFileList mruList = new MRUBundleFileList();
31
32     /**
33      * The bundle data
34      */

35     protected BaseData bundledata;
36     /**
37      * The zip file
38      */

39     protected ZipFile JavaDoc zipFile;
40     /**
41      * The closed flag
42      */

43     protected boolean closed = true;
44
45     /**
46      * Constructs a ZipBundle File
47      * @param basefile the base file
48      * @param bundledata the bundle data
49      * @throws IOException
50      */

51     public ZipBundleFile(File JavaDoc basefile, BaseData bundledata) throws IOException {
52         super(basefile);
53         if (!BundleFile.secureAction.exists(basefile))
54             throw new IOException(NLS.bind(AdaptorMsg.ADAPTER_FILEEXIST_EXCEPTION, basefile));
55         this.bundledata = bundledata;
56         this.closed = true;
57     }
58
59     /**
60      * Checks if the zip file is open
61      * @return true if the zip file is open
62      */

63     protected boolean checkedOpen() {
64         try {
65             return getZipFile() != null;
66         } catch (IOException e) {
67             if (bundledata != null)
68                 bundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundledata.getBundle(), e);
69             return false;
70         }
71     }
72
73     /**
74      * Opens the ZipFile for this bundle file
75      * @return an open ZipFile for this bundle file
76      * @throws IOException
77      */

78     protected ZipFile JavaDoc basicOpen() throws IOException {
79         return BundleFile.secureAction.getZipFile(this.basefile);
80     }
81
82     /**
83      * Returns an open ZipFile for this bundle file. If an open
84      * ZipFile does not exist then a new one is created and
85      * returned.
86      * @return an open ZipFile for this bundle
87      * @throws IOException
88      */

89     protected synchronized ZipFile JavaDoc getZipFile() throws IOException {
90         if (closed) {
91             mruList.add(this);
92             zipFile = basicOpen();
93             closed = false;
94         } else
95             mruList.use(this);
96         return zipFile;
97     }
98
99     /**
100     * Returns a ZipEntry for the bundle file. Must be called while synchronizing on this object.
101     * This method does not ensure that the ZipFile is opened. Callers may need to call getZipfile() prior to calling this
102     * method.
103     * @param path the path to an entry
104     * @return a ZipEntry or null if the entry does not exist
105     */

106     protected ZipEntry JavaDoc getZipEntry(String JavaDoc path) {
107         if (path.length() > 0 && path.charAt(0) == '/')
108             path = path.substring(1);
109         ZipEntry JavaDoc entry = zipFile.getEntry(path);
110         if (entry != null && entry.getSize() == 0 && !entry.isDirectory()) {
111             // work around the directory bug see bug 83542
112
ZipEntry JavaDoc dirEntry = zipFile.getEntry(path + '/');
113             if (dirEntry != null)
114                 entry = dirEntry;
115         }
116         return entry;
117     }
118
119     /**
120      * Extracts a directory and all sub content to disk
121      * @param dirName the directory name to extract
122      * @return the File used to extract the content to. A value
123      * of <code>null</code> is returned if the directory to extract does
124      * not exist or if content extraction is not supported.
125      */

126     protected synchronized File JavaDoc extractDirectory(String JavaDoc dirName) {
127         if (!checkedOpen())
128             return null;
129         Enumeration entries = zipFile.entries();
130         while (entries.hasMoreElements()) {
131             String JavaDoc entryPath = ((ZipEntry JavaDoc) entries.nextElement()).getName();
132             if (entryPath.startsWith(dirName) && !entryPath.endsWith("/")) //$NON-NLS-1$
133
getFile(entryPath, false);
134         }
135         return getExtractFile(dirName);
136     }
137
138     protected File JavaDoc getExtractFile(String JavaDoc entryName) {
139         if (bundledata == null)
140             return null;
141         String JavaDoc path = ".cp"; /* put all these entries in this subdir *///$NON-NLS-1$
142
String JavaDoc name = entryName.replace('/', File.separatorChar);
143         if ((name.length() > 1) && (name.charAt(0) == File.separatorChar)) /* if name has a leading slash */
144             path = path.concat(name);
145         else
146             path = path + File.separator + name;
147         return bundledata.getExtractFile(path);
148     }
149
150     public synchronized File JavaDoc getFile(String JavaDoc entry, boolean nativeCode) {
151         if (!checkedOpen())
152             return null;
153         ZipEntry JavaDoc zipEntry = getZipEntry(entry);
154         if (zipEntry == null)
155             return null;
156
157         try {
158             File JavaDoc nested = getExtractFile(zipEntry.getName());
159             if (nested != null) {
160                 if (nested.exists()) {
161                     /* the entry is already cached */
162                     if (Debug.DEBUG && Debug.DEBUG_GENERAL)
163                         Debug.println("File already present: " + nested.getPath()); //$NON-NLS-1$
164
if (nested.isDirectory())
165                         // must ensure the complete directory is extracted (bug 182585)
166
extractDirectory(zipEntry.getName());
167                 } else {
168                     if (zipEntry.getName().endsWith("/")) { //$NON-NLS-1$
169
if (!nested.mkdirs()) {
170                             if (Debug.DEBUG && Debug.DEBUG_GENERAL)
171                                 Debug.println("Unable to create directory: " + nested.getPath()); //$NON-NLS-1$
172
throw new IOException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, nested.getAbsolutePath()));
173                         }
174                         extractDirectory(zipEntry.getName());
175                     } else {
176                         InputStream in = zipFile.getInputStream(zipEntry);
177                         if (in == null)
178                             return null;
179                         /* the entry has not been cached */
180                         if (Debug.DEBUG && Debug.DEBUG_GENERAL)
181                             Debug.println("Creating file: " + nested.getPath()); //$NON-NLS-1$
182
/* create the necessary directories */
183                         File JavaDoc dir = new File JavaDoc(nested.getParent());
184                         if (!dir.exists() && !dir.mkdirs()) {
185                             if (Debug.DEBUG && Debug.DEBUG_GENERAL)
186                                 Debug.println("Unable to create directory: " + dir.getPath()); //$NON-NLS-1$
187
throw new IOException(NLS.bind(AdaptorMsg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, dir.getAbsolutePath()));
188                         }
189                         /* copy the entry to the cache */
190                         AdaptorUtil.readFile(in, nested);
191                         if (nativeCode)
192                             setPermissions(nested);
193                     }
194                 }
195
196                 return nested;
197             }
198         } catch (IOException e) {
199             if (Debug.DEBUG && Debug.DEBUG_GENERAL)
200                 Debug.printStackTrace(e);
201         }
202         return null;
203     }
204
205     public synchronized boolean containsDir(String JavaDoc dir) {
206         if (!checkedOpen())
207             return false;
208         if (dir == null)
209             return false;
210
211         if (dir.length() == 0)
212             return true;
213
214         if (dir.charAt(0) == '/') {
215             if (dir.length() == 1)
216                 return true;
217             dir = dir.substring(1);
218         }
219
220         if (dir.length() > 0 && dir.charAt(dir.length() - 1) != '/')
221             dir = dir + '/';
222
223         Enumeration entries = zipFile.entries();
224         ZipEntry JavaDoc zipEntry;
225         String JavaDoc entryPath;
226         while (entries.hasMoreElements()) {
227             zipEntry = (ZipEntry JavaDoc) entries.nextElement();
228             entryPath = zipEntry.getName();
229             if (entryPath.startsWith(dir)) {
230                 return true;
231             }
232         }
233         return false;
234     }
235
236     public synchronized BundleEntry getEntry(String JavaDoc path) {
237         if (!checkedOpen())
238             return null;
239         ZipEntry JavaDoc zipEntry = getZipEntry(path);
240         if (zipEntry == null) {
241             if (path.length() == 0 || path.charAt(path.length() - 1) == '/') {
242                 // this is a directory request lets see if any entries exist in this directory
243
if (containsDir(path))
244                     return new DirZipBundleEntry(this, path);
245             }
246             return null;
247         }
248
249         return new ZipBundleEntry(zipEntry, this);
250
251     }
252
253     public synchronized Enumeration getEntryPaths(String JavaDoc path) {
254         if (!checkedOpen())
255             return null;
256         if (path == null)
257             throw new NullPointerException JavaDoc();
258
259         if (path.length() > 0 && path.charAt(0) == '/')
260             path = path.substring(1);
261         if (path.length() > 0 && path.charAt(path.length() - 1) != '/')
262             path = new StringBuffer JavaDoc(path).append("/").toString(); //$NON-NLS-1$
263

264         Vector vEntries = new Vector();
265         Enumeration entries = zipFile.entries();
266         while (entries.hasMoreElements()) {
267             ZipEntry JavaDoc zipEntry = (ZipEntry JavaDoc) entries.nextElement();
268             String JavaDoc entryPath = zipEntry.getName();
269             if (entryPath.startsWith(path)) {
270                 if (path.length() < entryPath.length()) {
271                     if (entryPath.lastIndexOf('/') < path.length()) {
272                         vEntries.add(entryPath);
273                     } else {
274                         entryPath = entryPath.substring(path.length());
275                         int slash = entryPath.indexOf('/');
276                         entryPath = path + entryPath.substring(0, slash + 1);
277                         if (!vEntries.contains(entryPath))
278                             vEntries.add(entryPath);
279                     }
280                 }
281             }
282         }
283         return vEntries.size() == 0 ? null : vEntries.elements();
284     }
285
286     public synchronized void close() throws IOException {
287         if (!closed) {
288             closed = true;
289             zipFile.close();
290             mruList.remove(this);
291         }
292     }
293
294     public void open() throws IOException {
295         //do nothing
296
}
297
298     /**
299      * Shutsdown the bundle file closer thread for zip bundle files
300      */

301     public static void shutdown() {
302         mruList.shutdown();
303     }
304 }
305
Popular Tags