KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > enhancer > util > ClassPathElement


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24
25 package com.sun.jdo.api.persistence.enhancer.util;
26
27 import java.util.Enumeration JavaDoc;
28 import java.util.NoSuchElementException JavaDoc;
29 import java.io.File JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.io.FilenameFilter JavaDoc;
32 import java.util.zip.ZipFile JavaDoc;
33 import java.util.zip.ZipEntry JavaDoc;
34
35 /**
36  * Abstract base class for components of a class path.
37  */

38
39 abstract class ClassPathElement {
40
41   /* A link to the next element in the path */
42   private ClassPathElement next;
43
44   /* package local accessors */
45
46   /**
47    * If this class path element resolves the class, return a
48    * ClassFileSource for the class.
49    */

50   public abstract ClassFileSource sourceOf(String JavaDoc className);
51
52   /**
53    * Return an enumeration of all of the class files in the specified
54    * package in this class path element.
55    *
56    * @param packageName specifies the VM format package name
57    * to which class files must belong.
58    * @returns an Enumeration of the VM format class names which
59    * can be found. The return value may be null if the class
60    * path element is not valid.
61    */

62   public abstract Enumeration JavaDoc classesInPackage(String JavaDoc packageName);
63
64   /**
65    * Check to see if this ClassPathElement is a directory matching
66    * the directory passed in.
67    */

68   abstract boolean matches(File JavaDoc directory);
69
70   /**
71    * Return the next class path element in the chain
72    */

73   ClassPathElement next() {
74     return this.next;
75   }
76
77   /**
78    * Set the the next class path element in the chain
79    */

80   void setNext(ClassPathElement next) {
81     this.next = next;
82   }
83
84   /**
85    * Construct a class path element
86    */

87   ClassPathElement() {
88   }
89
90   /**
91    * Create an appropriate type of class path element based on the
92    * path element name.
93    */

94   static ClassPathElement create(String JavaDoc elementSpec) {
95     File JavaDoc element = new File JavaDoc(elementSpec);
96     if (!element.isDirectory() &&
97     looksLikeZipName(elementSpec))
98       return new ZipFileClassPathElement(element);
99     else
100       return new DirectoryClassPathElement(element);
101   }
102
103   /**
104    * Append a class path element to the chain
105    */

106   void append(ClassPathElement another) {
107     ClassPathElement e = this;
108     while (e.next() != null)
109       e = e.next();
110     e.next = another;
111   }
112
113   /**
114    * Check whether the String "looks" like a zip file name.
115    */

116   static protected boolean looksLikeZipName(String JavaDoc fname) {
117     return (fname.length() > 4 &&
118         (fname.regionMatches(true, fname.length() - 4, ".zip", 0, 4) ||//NOI18N
119
fname.regionMatches(true, fname.length() - 4, ".jar", 0, 4)));//NOI18N
120
}
121
122 }
123
124 /**
125  * DirectoryClassPathElement represents a component of a class path
126  * which is believe to be a directory.
127  */

128
129 class DirectoryClassPathElement extends ClassPathElement {
130
131   private File JavaDoc directory;
132
133   private boolean exists;
134
135   /* package local accessors */
136
137   /**
138    * If this class path element resolves the class, return a
139    * ClassFileSource for the class.
140    */

141   public ClassFileSource sourceOf(String JavaDoc className) {
142     File JavaDoc f = fileOf(className);
143     if (f != null && f.exists()) {
144       return new ClassFileSource(className, f);
145     }
146     return null;
147   }
148
149   public Enumeration JavaDoc classesInPackage(String JavaDoc packageName) {
150     if (!exists)
151       return null;
152
153     return new DirectoryClassPackageEnumerator(directory, packageName);
154   }
155
156   boolean matches(File JavaDoc matchDirectory) {
157     String JavaDoc dir = FilePath.canonicalize(directory);
158     String JavaDoc matchDir = FilePath.canonicalize(matchDirectory);
159     return FilePath.canonicalNamesEqual(dir, matchDir);
160   }
161
162   /**
163    * Construct a class path element
164    */

165   DirectoryClassPathElement(File JavaDoc dirSpec) {
166     directory = dirSpec;
167     checkValid();
168   }
169
170   /* private methods */
171
172   /**
173    * fileOf Return a File object which might reasonably contain the
174    * specified class. The contents may or may not be valid.
175    */

176   private File JavaDoc fileOf(String JavaDoc className) {
177     if (exists && directory.isDirectory()) {
178       StringBuffer JavaDoc newPath = new StringBuffer JavaDoc(directory.getPath());
179       if (newPath.charAt(newPath.length() - 1) != File.separatorChar)
180     newPath.append(File.separatorChar);
181       newPath.append(ClassPath.fileNameOf(className));
182
183       File JavaDoc f = new File JavaDoc(newPath.toString());
184       if (f.isFile())
185     return f;
186     }
187
188     return null;
189   }
190
191   /**
192    * Is this class path element valid? That is, does the directory
193    * exist with the specified name?
194    */

195   private boolean isValid() {
196     return exists;
197   }
198
199   private void checkValid() {
200     exists = directory.isDirectory();
201   }
202 }
203
204 /**
205  * ZipFileClassPathElement represents a component of a class path
206  * which is believe to be a zip file containing classes.
207  */

208
209 class ZipFileClassPathElement extends ClassPathElement {
210
211   private File JavaDoc zipFileElement;
212   private ZipFile JavaDoc zipFile;
213
214   /* package local accessors */
215
216   /**
217    * If this class path element resolves the class, return a
218    * ClassFileSource for the class.
219    */

220   public ClassFileSource sourceOf(String JavaDoc className) {
221     if (zipFile != null) {
222       ZipEntry JavaDoc entry =
223     zipFile.getEntry(ClassPath.zipFileNameOf(className));
224       if (entry != null) {
225     return new ClassFileSource(className, zipFile);
226       }
227     }
228     return null;
229   }
230
231   public Enumeration JavaDoc classesInPackage(String JavaDoc packageName) {
232     if (zipFile == null)
233       return null;
234
235     return new ZipFileClassPackageEnumerator(zipFile, packageName);
236   }
237
238   boolean matches(File JavaDoc directory) {
239     return false;
240   }
241
242   /**
243    * Construct a zip file class path element
244    */

245   ZipFileClassPathElement(File JavaDoc elementSpec) {
246     zipFileElement = elementSpec;
247     checkValid();
248   }
249
250   /* private methods */
251
252   private void checkValid() {
253     if (looksLikeZipName(zipFileElement.getPath()) &&
254     zipFileElement.isFile()) {
255       try {
256     zipFile = ZipFileRegistry.openZipFile(zipFileElement);
257       } catch (IOException JavaDoc e) {
258     System.err.println("IO exception while reading " +
259                zipFileElement.getPath());
260     zipFile = null;
261       }
262     }
263   }
264 }
265
266
267 /**
268  * An enumeration class which returns the names of the classes which
269  * can be found relative to a particular directory.
270  */

271
272 class DirectoryClassPackageEnumerator
273   implements Enumeration JavaDoc, FilenameFilter JavaDoc {
274
275   private String JavaDoc[] matches;
276   private int nextMatch = -1;
277   String JavaDoc searchPackage;
278
279   /**
280    * Constructor
281    * @param directory The directory to be used as the root of the
282    * package structure.
283    * @param packageName The name of the package to search (in VM form).
284    */

285   DirectoryClassPackageEnumerator(File JavaDoc directory, String JavaDoc packageName) {
286     searchPackage = packageName;
287     String JavaDoc packageDirName = directory.getPath() + File.separator +
288       packageName.replace('/', File.separatorChar);
289
290     File JavaDoc packageDir = new File JavaDoc(packageDirName);
291     if (packageDir.isDirectory()) {
292       matches = packageDir.list(this);
293       if (matches != null && matches.length > 0)
294     nextMatch = 0;
295     }
296   }
297
298   public boolean hasMoreElements() {
299     return (nextMatch >= 0);
300   }
301
302   public Object JavaDoc nextElement() {
303     if (!hasMoreElements())
304       throw new NoSuchElementException JavaDoc();
305     String JavaDoc next = matches[nextMatch++];
306     if (nextMatch >= matches.length)
307       nextMatch = -1;
308     return ClassPath.classNameOf(searchPackage + "/" + next);//NOI18N
309
}
310
311   /**
312    * Check whether the file name is valid.
313    * Needed for FilenameFilter implementation.
314    */

315
316   public boolean accept(File JavaDoc dir, String JavaDoc name) {
317     int nameLength = name.length();
318     boolean isOk = (nameLength > 6 &&
319             name.regionMatches(true, nameLength - 6, ".class", 0, 6));//NOI18N
320
return isOk;
321   }
322
323 }
324
325 /**
326  * An enumeration class which returns the names of the classes which
327  * can be found within a zip file.
328  */

329
330 class ZipFileClassPackageEnumerator implements Enumeration JavaDoc {
331   Enumeration JavaDoc zipFileEntries;
332   ZipEntry JavaDoc nextEntry;
333   String JavaDoc packageName;
334
335   ZipFileClassPackageEnumerator(ZipFile JavaDoc zipFile, String JavaDoc packageName) {
336     zipFileEntries = zipFile.entries();
337     this.packageName = packageName;
338   }
339
340   public boolean hasMoreElements() {
341     while (nextEntry == null && zipFileEntries != null &&
342        zipFileEntries.hasMoreElements()) {
343       ZipEntry JavaDoc ent = (ZipEntry JavaDoc) zipFileEntries.nextElement();
344       String JavaDoc memName = ent.getName();
345       int memNameLength = memName.length();
346       int packageNameLength = packageName.length();
347
348       /* Check that the package name is a prefix of the member name.
349      Note that we rely here on the fact that zip file have a separator
350      character identical to the VM package separator */

351
352       if (memNameLength > packageNameLength + 1 &&
353       memName.regionMatches(false, 0, packageName,
354                 0, packageNameLength) &&
355       memName.charAt(packageNameLength) == '/') {
356     if (memName.indexOf('/', packageNameLength+1) == -1) {
357       boolean isOk =
358         (memNameLength > packageNameLength+7 &&
359          memName.regionMatches(true, memNameLength - 6, ".class", 0, 6));//NOI18N
360
if (isOk)
361         nextEntry = ent;
362     }
363       }
364     }
365     return nextEntry != null;
366   }
367
368   public Object JavaDoc nextElement() {
369     if (!hasMoreElements())
370       throw new NoSuchElementException JavaDoc();
371     String JavaDoc className = nextEntry.getName();
372     nextEntry = null;
373     return ClassPath.classNameOf(className);
374   }
375 }
376
Popular Tags