KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > JarPackageFragmentRoot


1 /*******************************************************************************
2  * Copyright (c) 2000, 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 package org.eclipse.jdt.internal.core;
12
13 import java.util.*;
14 import java.util.zip.ZipEntry JavaDoc;
15 import java.util.zip.ZipFile JavaDoc;
16
17 import org.eclipse.core.resources.IResource;
18 import org.eclipse.core.resources.ResourcesPlugin;
19 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.core.runtime.IPath;
21 import org.eclipse.jdt.core.*;
22 import org.eclipse.jdt.core.compiler.CharOperation;
23 import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
24 import org.eclipse.jdt.internal.core.util.Util;
25
26 /**
27  * A package fragment root that corresponds to a .jar or .zip.
28  *
29  * <p>NOTE: The only visible entries from a .jar or .zip package fragment root
30  * are .class files.
31  * <p>NOTE: A jar package fragment root may or may not have an associated resource.
32  *
33  * @see org.eclipse.jdt.core.IPackageFragmentRoot
34  * @see org.eclipse.jdt.internal.core.JarPackageFragmentRootInfo
35  */

36 public class JarPackageFragmentRoot extends PackageFragmentRoot {
37     
38     public final static ArrayList EMPTY_LIST = new ArrayList();
39     
40     /**
41      * The path to the jar file
42      * (a workspace relative path if the jar is internal,
43      * or an OS path if the jar is external)
44      */

45     protected final IPath jarPath;
46
47     /**
48      * Constructs a package fragment root which is the root of the Java package directory hierarchy
49      * based on a JAR file that is not contained in a <code>IJavaProject</code> and
50      * does not have an associated <code>IResource</code>.
51      */

52     protected JarPackageFragmentRoot(IPath jarPath, JavaProject project) {
53         super(null, project);
54         this.jarPath = jarPath;
55     }
56     /**
57      * Constructs a package fragment root which is the root of the Java package directory hierarchy
58      * based on a JAR file.
59      */

60     protected JarPackageFragmentRoot(IResource resource, JavaProject project) {
61         super(resource, project);
62         this.jarPath = resource.getFullPath();
63     }
64
65     /**
66      * Compute the package fragment children of this package fragment root.
67      * These are all of the directory zip entries, and any directories implied
68      * by the path of class files contained in the jar of this package fragment root.
69      * Has the side effect of opening the package fragment children.
70      */

71     protected boolean computeChildren(OpenableElementInfo info, Map newElements) throws JavaModelException {
72         
73         ArrayList vChildren= new ArrayList();
74         final int JAVA = 0;
75         final int NON_JAVA = 1;
76         ZipFile JavaDoc jar= null;
77         try {
78             jar= getJar();
79     
80             HashtableOfArrayToObject packageFragToTypes= new HashtableOfArrayToObject();
81     
82             // always create the default package
83
packageFragToTypes.put(CharOperation.NO_STRINGS, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
84     
85             for (Enumeration e= jar.entries(); e.hasMoreElements();) {
86                 ZipEntry JavaDoc member= (ZipEntry JavaDoc) e.nextElement();
87                 initPackageFragToTypes(packageFragToTypes, member.getName(), member.isDirectory());
88             }
89             
90             //loop through all of referenced packages, creating package fragments if necessary
91
// and cache the entry names in the infos created for those package fragments
92
for (int i = 0, length = packageFragToTypes.keyTable.length; i < length; i++) {
93                 String JavaDoc[] pkgName = (String JavaDoc[]) packageFragToTypes.keyTable[i];
94                 if (pkgName == null) continue;
95                 
96                 ArrayList[] entries= (ArrayList[]) packageFragToTypes.get(pkgName);
97                 JarPackageFragment packFrag= (JarPackageFragment) getPackageFragment(pkgName);
98                 JarPackageFragmentInfo fragInfo= new JarPackageFragmentInfo();
99                 int resLength= entries[NON_JAVA].size();
100                 if (resLength == 0) {
101                     packFrag.computeNonJavaResources(CharOperation.NO_STRINGS, packFrag, fragInfo, jar.getName());
102                 } else {
103                     String JavaDoc[] resNames= new String JavaDoc[resLength];
104                     entries[NON_JAVA].toArray(resNames);
105                     packFrag.computeNonJavaResources(resNames, packFrag, fragInfo, jar.getName());
106                 }
107                 packFrag.computeChildren(fragInfo, entries[JAVA]);
108                 newElements.put(packFrag, fragInfo);
109                 vChildren.add(packFrag);
110             }
111         } catch (CoreException e) {
112             if (e instanceof JavaModelException) throw (JavaModelException)e;
113             throw new JavaModelException(e);
114         } finally {
115             JavaModelManager.getJavaModelManager().closeZipFile(jar);
116         }
117
118
119         IJavaElement[] children= new IJavaElement[vChildren.size()];
120         vChildren.toArray(children);
121         info.setChildren(children);
122         return true;
123     }
124     /**
125      * Returns a new element info for this element.
126      */

127     protected Object JavaDoc createElementInfo() {
128         return new JarPackageFragmentRootInfo();
129     }
130     /**
131      * A Jar is always K_BINARY.
132      */

133     protected int determineKind(IResource underlyingResource) {
134         return IPackageFragmentRoot.K_BINARY;
135     }
136     /**
137      * Returns true if this handle represents the same jar
138      * as the given handle. Two jars are equal if they share
139      * the same zip file.
140      *
141      * @see Object#equals
142      */

143     public boolean equals(Object JavaDoc o) {
144         if (this == o)
145             return true;
146         if (o instanceof JarPackageFragmentRoot) {
147             JarPackageFragmentRoot other= (JarPackageFragmentRoot) o;
148             return this.jarPath.equals(other.jarPath);
149         }
150         return false;
151     }
152     public String JavaDoc getElementName() {
153         return this.jarPath.lastSegment();
154     }
155     /**
156      * Returns the underlying ZipFile for this Jar package fragment root.
157      *
158      * @exception CoreException if an error occurs accessing the jar
159      */

160     public ZipFile JavaDoc getJar() throws CoreException {
161         return JavaModelManager.getJavaModelManager().getZipFile(getPath());
162     }
163     /**
164      * @see IPackageFragmentRoot
165      */

166     public int getKind() {
167         return IPackageFragmentRoot.K_BINARY;
168     }
169     /**
170      * Returns an array of non-java resources contained in the receiver.
171      */

172     public Object JavaDoc[] getNonJavaResources() throws JavaModelException {
173         // We want to show non java resources of the default package at the root (see PR #1G58NB8)
174
Object JavaDoc[] defaultPkgResources = ((JarPackageFragment) getPackageFragment(CharOperation.NO_STRINGS)).storedNonJavaResources();
175         int length = defaultPkgResources.length;
176         if (length == 0)
177             return defaultPkgResources;
178         Object JavaDoc[] nonJavaResources = new Object JavaDoc[length];
179         for (int i = 0; i < length; i++) {
180             JarEntryResource nonJavaResource = (JarEntryResource) defaultPkgResources[i];
181             nonJavaResources[i] = nonJavaResource.clone(this);
182         }
183         return nonJavaResources;
184     }
185     public PackageFragment getPackageFragment(String JavaDoc[] pkgName) {
186         return new JarPackageFragment(this, pkgName);
187     }
188     /**
189      * @see IPackageFragmentRoot
190      */

191     public IPath getPath() {
192         if (isExternal()) {
193             return this.jarPath;
194         } else {
195             return super.getPath();
196         }
197     }
198     public IResource getResource() {
199         if (this.resource == null) {
200             this.resource = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), this.jarPath, false);
201         }
202         if (this.resource instanceof IResource) {
203             return super.getResource();
204         } else {
205             // external jar
206
return null;
207         }
208     }
209
210
211     /**
212      * @see IJavaElement
213      */

214     public IResource getUnderlyingResource() throws JavaModelException {
215         if (isExternal()) {
216             if (!exists()) throw newNotPresentException();
217             return null;
218         } else {
219             return super.getUnderlyingResource();
220         }
221     }
222     public int hashCode() {
223         return this.jarPath.hashCode();
224     }
225     private void initPackageFragToTypes(HashtableOfArrayToObject packageFragToTypes, String JavaDoc entryName, boolean isDirectory) {
226         int lastSeparator = isDirectory ? entryName.length()-1 : entryName.lastIndexOf('/');
227         String JavaDoc[] pkgName = Util.splitOn('/', entryName, 0, lastSeparator);
228         String JavaDoc[] existing = null;
229         int length = pkgName.length;
230         int existingLength = length;
231         while (existingLength >= 0) {
232             existing = (String JavaDoc[]) packageFragToTypes.getKey(pkgName, existingLength);
233             if (existing != null) break;
234             existingLength--;
235         }
236         JavaModelManager manager = JavaModelManager.getJavaModelManager();
237         IJavaProject project = getJavaProject();
238         for (int i = existingLength; i < length; i++) {
239             if (Util.isValidFolderNameForPackage(pkgName[i], project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true))) {
240                 System.arraycopy(existing, 0, existing = new String JavaDoc[i+1], 0, i);
241                 existing[i] = manager.intern(pkgName[i]);
242                 packageFragToTypes.put(existing, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
243             } else {
244                 // non-Java resource folder
245
if (!isDirectory) {
246                     ArrayList[] children = (ArrayList[]) packageFragToTypes.get(existing);
247                     if (children[1/*NON_JAVA*/] == EMPTY_LIST) children[1/*NON_JAVA*/] = new ArrayList();
248                     children[1/*NON_JAVA*/].add(entryName);
249                 }
250                 return;
251             }
252         }
253         if (isDirectory)
254             return;
255         
256         // add classfile info amongst children
257
ArrayList[] children = (ArrayList[]) packageFragToTypes.get(pkgName);
258         if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
259             if (children[0/*JAVA*/] == EMPTY_LIST) children[0/*JAVA*/] = new ArrayList();
260             String JavaDoc fileName = entryName.substring(lastSeparator + 1);
261             children[0/*JAVA*/].add(fileName);
262         } else {
263             if (children[1/*NON_JAVA*/] == EMPTY_LIST) children[1/*NON_JAVA*/] = new ArrayList();
264             children[1/*NON_JAVA*/].add(entryName);
265         }
266         
267     }
268     /**
269      * @see IPackageFragmentRoot
270      */

271     public boolean isArchive() {
272         return true;
273     }
274     /**
275      * @see IPackageFragmentRoot
276      */

277     public boolean isExternal() {
278         return getResource() == null;
279     }
280     /**
281      * Jars and jar entries are all read only
282      */

283     public boolean isReadOnly() {
284         return true;
285     }
286
287     /**
288  * Returns whether the corresponding resource or associated file exists
289  */

290 protected boolean resourceExists() {
291     if (this.isExternal()) {
292         return
293             JavaModel.getTarget(
294                 ResourcesPlugin.getWorkspace().getRoot(),
295                 this.getPath(), // don't make the path relative as this is an external archive
296
true) != null;
297     } else {
298         return super.resourceExists();
299     }
300 }
301 protected void toStringAncestors(StringBuffer JavaDoc buffer) {
302     if (isExternal())
303         // don't show project as it is irrelevant for external jar files.
304
// also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=146615
305
return;
306     super.toStringAncestors(buffer);
307 }
308 }
309
Popular Tags