KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > core > sourcelookup > containers > ExternalArchiveSourceContainer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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 package org.eclipse.debug.core.sourcelookup.containers;
12
13 import java.io.File JavaDoc;
14 import java.io.IOException JavaDoc;
15 import com.ibm.icu.text.MessageFormat;
16 import java.util.ArrayList JavaDoc;
17 import java.util.Enumeration JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Set JavaDoc;
22 import java.util.zip.ZipEntry JavaDoc;
23 import java.util.zip.ZipFile JavaDoc;
24
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.debug.core.DebugPlugin;
27 import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
28 import org.eclipse.debug.internal.core.sourcelookup.SourceLookupMessages;
29 import org.eclipse.debug.internal.core.sourcelookup.SourceLookupUtils;
30
31 /**
32  * An archive in the local file system. Returns instances
33  * of <code>ZipEntryStorage</code> as source elements.
34  * <p>
35  * Clients may instantiate this class. This class is not intended to
36  * be subclassed.
37  * </p>
38  * @since 3.0
39  */

40 public class ExternalArchiveSourceContainer extends AbstractSourceContainer {
41     
42     private boolean fDetectRoots = false;
43     private Set JavaDoc fPotentialRoots = null;
44     private List JavaDoc fRoots = new ArrayList JavaDoc();
45     private String JavaDoc fArchivePath = null;
46     /**
47      * Unique identifier for the external archive source container type
48      * (value <code>org.eclipse.debug.core.containerType.externalArchive</code>).
49      */

50     public static final String JavaDoc TYPE_ID = DebugPlugin.getUniqueIdentifier() + ".containerType.externalArchive"; //$NON-NLS-1$
51

52     /**
53      * Creates an archive source container on the archive at the
54      * specified location in the local file system.
55      *
56      * @param archivePath path to the archive in the local file system
57      * @param detectRootPaths whether root container paths should be detected. When
58      * <code>true</code>, searching is performed relative to a root path
59      * within the archive based on fully qualified file names. A root
60      * path is automatically determined for when the first
61      * successful search is performed. For example, when searching for a file
62      * named <code>a/b/c.d</code>, and an entry in the archive named
63      * <code>r/a/b/c.d</code> exists, a root path is set to <code>r</code>.
64      * When searching for an unqualified file name, root containers are not
65      * considered.
66      * When <code>false</code>, searching is performed by
67      * matching file names as suffixes to the entries in the archive.
68      */

69     public ExternalArchiveSourceContainer(String JavaDoc archivePath, boolean detectRootPaths) {
70         fArchivePath = archivePath;
71         fDetectRoots = detectRootPaths;
72     }
73     
74     /* (non-Javadoc)
75      * @see org.eclipse.debug.core.sourcelookup.ISourceContainer#findSourceElements(java.lang.String)
76      */

77     public Object JavaDoc[] findSourceElements(String JavaDoc name) throws CoreException {
78         name = name.replace('\\', '/');
79         ZipFile JavaDoc file = getArchive();
80         synchronized (file) {
81             boolean isQualfied = name.indexOf('/') > 0;
82             if (fDetectRoots && isQualfied) {
83                 ZipEntry JavaDoc entry = searchRoots(file, name);
84                 if (entry != null) {
85                     return new Object JavaDoc[]{new ZipEntryStorage(file, entry)};
86                 }
87             } else {
88                 // try exact match
89
ZipEntry JavaDoc entry = file.getEntry(name);
90                 if (entry != null) {
91                     // can't be any duplicates if there is an exact match
92
return new Object JavaDoc[]{new ZipEntryStorage(file, entry)};
93                 }
94                 // search
95
Enumeration JavaDoc entries = file.entries();
96                 List JavaDoc matches = null;
97                 while (entries.hasMoreElements()) {
98                     entry = (ZipEntry JavaDoc)entries.nextElement();
99                     String JavaDoc entryName = entry.getName();
100                     if (entryName.endsWith(name)) {
101                         if (isQualfied || entryName.length() == name.length() || entryName.charAt(entryName.length() - name.length() - 1) == '/') {
102                             if (isFindDuplicates()) {
103                                 if (matches == null) {
104                                     matches = new ArrayList JavaDoc();
105                                 }
106                                 matches.add(new ZipEntryStorage(file, entry));
107                             } else {
108                                 return new Object JavaDoc[]{new ZipEntryStorage(file, entry)};
109                             }
110                         }
111                     }
112                 }
113                 if (matches != null) {
114                     return matches.toArray();
115                 }
116             }
117         }
118         return EMPTY;
119     }
120     
121     /**
122      * Returns the root path in this archive for the given file name, based
123      * on its type, or <code>null</code> if none. Detects a root if a root has
124      * not yet been detected for the given file type.
125      *
126      * @param file zip file to search in
127      * @param name file name
128      * @exception CoreException if an exception occurs while detecting the root
129      */

130     private ZipEntry JavaDoc searchRoots(ZipFile JavaDoc file, String JavaDoc name) {
131         if (fPotentialRoots == null) {
132             fPotentialRoots = new HashSet JavaDoc();
133             fPotentialRoots.add(""); //$NON-NLS-1$
134
// all potential roots are the directories
135
Enumeration JavaDoc entries = file.entries();
136             while (entries.hasMoreElements()) {
137                 ZipEntry JavaDoc entry = (ZipEntry JavaDoc) entries.nextElement();
138                 if (entry.isDirectory()) {
139                     fPotentialRoots.add(entry.getName());
140                 } else {
141                     String JavaDoc entryName = entry.getName();
142                     int index = entryName.lastIndexOf("/"); //$NON-NLS-1$
143
while (index > 0) {
144                         if (fPotentialRoots.add(entryName.substring(0, index + 1))) {
145                             entryName = entryName.substring(0, index);
146                             index = entryName.lastIndexOf("/"); //$NON-NLS-1$
147
} else {
148                             break;
149                         }
150                     }
151                 }
152             }
153         }
154         int i = 0;
155         while (i < fRoots.size()) {
156             String JavaDoc root = (String JavaDoc) fRoots.get(i);
157             ZipEntry JavaDoc entry = file.getEntry(root+name);
158             if (entry != null) {
159                 return entry;
160             }
161             i++;
162         }
163         if (!fPotentialRoots.isEmpty()) {
164             Iterator JavaDoc roots = fPotentialRoots.iterator();
165             String JavaDoc root = null;
166             ZipEntry JavaDoc entry = null;
167             while (roots.hasNext()) {
168                 root = (String JavaDoc) roots.next();
169                 entry = file.getEntry(root+name);
170                 if (entry != null) {
171                     break;
172                 }
173             }
174             if (entry != null) {
175                 if (root != null) {
176                     fRoots.add(root);
177                     fPotentialRoots.remove(root);
178                     // remove any roots that begin with the new root, as roots cannot be nested
179
Iterator JavaDoc rs = fPotentialRoots.iterator();
180                     while (rs.hasNext()) {
181                         String JavaDoc r = (String JavaDoc) rs.next();
182                         if (r.startsWith(root)) {
183                             rs.remove();
184                         }
185                     }
186                 }
187                 return entry;
188             }
189         }
190         return null;
191     }
192
193     /**
194      * Returns the archive to search in.
195      *
196      * @throws CoreException if unable to access the archive
197      */

198     private ZipFile JavaDoc getArchive() throws CoreException {
199         try {
200             return SourceLookupUtils.getZipFile(fArchivePath);
201         } catch (IOException JavaDoc e) {
202             File JavaDoc file = new File JavaDoc(fArchivePath);
203             if (file.exists()) {
204                 abort(MessageFormat.format(SourceLookupMessages.ExternalArchiveSourceContainer_2, new String JavaDoc[]{fArchivePath}), e);
205             } else {
206                 warn(MessageFormat.format(SourceLookupMessages.ExternalArchiveSourceContainer_1, new String JavaDoc[]{fArchivePath}), e);
207             }
208         }
209         return null;
210     }
211
212     /* (non-Javadoc)
213      * @see org.eclipse.debug.core.sourcelookup.ISourceContainer#getName()
214      */

215     public String JavaDoc getName() {
216         return fArchivePath;
217     }
218     /* (non-Javadoc)
219      * @see org.eclipse.debug.core.sourcelookup.ISourceContainer#getType()
220      */

221     public ISourceContainerType getType() {
222         return getSourceContainerType(TYPE_ID);
223     }
224     
225     /**
226      * Returns whether root paths are automatically detected in this
227      * archive source container.
228      *
229      * @return whether root paths are automatically detected in this
230      * archive source container
231      */

232     public boolean isDetectRoot() {
233         return fDetectRoots;
234     }
235     /* (non-Javadoc)
236      * @see java.lang.Object#equals(java.lang.Object)
237      */

238     public boolean equals(Object JavaDoc obj) {
239         return obj instanceof ExternalArchiveSourceContainer &&
240             ((ExternalArchiveSourceContainer)obj).getName().equals(getName());
241     }
242     /* (non-Javadoc)
243      * @see java.lang.Object#hashCode()
244      */

245     public int hashCode() {
246         return getName().hashCode();
247     }
248     
249     /*
250      * (non-Javadoc)
251      * @see org.eclipse.debug.core.sourcelookup.ISourceContainer#dispose()
252      */

253     public void dispose() {
254         super.dispose();
255         if (fPotentialRoots != null) {
256             fPotentialRoots.clear();
257         }
258         fRoots.clear();
259     }
260 }
261
Popular Tags