KickJava   Java API By Example, From Geeks To Geeks.

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


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 //@lars: removed openide-dependencies
28
//@olsen: not needed
29
//import com.sun.jdo.api.persistence.enhancer.FilterEnv;
30
//@olsen: added: support for I18N
31
//@olsen: subst: FilterError -> UserException, assert()
32

33 import java.util.zip.ZipFile JavaDoc;
34 import java.util.zip.ZipEntry JavaDoc;
35 import java.io.*;
36 import java.util.*;
37 //@yury: added ability to get the class bytecode from the Forte4J archive entry
38
//import org.openidex.jarpackager.ArchiveEntry;
39

40 /**
41  * ClassFileSource provides a mechanism for associating a class
42  * with the source of that class. The source is currently either
43  * an ordinary .class file or a zip file 1 or more class files.
44  */

45 //^olsen: cosmetics (indentation, control flow ...)
46
public class ClassFileSource
47   extends Support {
48
49   /* The original expected name of the class */
50   private String JavaDoc theOriginalExpectedClassName = null;
51
52   /* The expected name of the class */
53   private String JavaDoc theExpectedClassName = null;
54
55   /* The file containing the class file */
56   private File JavaDoc classFile = null;
57
58   /* The zip file containing the class file */
59   private ZipFile JavaDoc zipFile = null;
60
61   /* The byte-code input stream from a class file */
62   private InputStream byteCodeStream = null;
63
64   /* The ClassPathElement through which this was located */
65   private ClassPathElement sourceElement;
66
67   /* The cached modification date */
68   private long cachedModDate;
69 // private ArchiveEntry archiveEntry; //@yury: added ability to get the class bytecode from the Forte4J archive entry
70

71     //@yury archive entry getter
72
/**
73      * @return The ArchiveEntry
74      */

75      /*
76     public ArchiveEntry getArchiveEntry() {
77     return archiveEntry;
78     }
79     */

80
81   /* public access */
82
83   /**
84    * Does the other class file source refer to the same source location?
85    */

86   public boolean sameAs(ClassFileSource other) {
87
88 /*
89       //@yury: added ArchiveEntry processing [[[[
90       if ((null == getArchiveEntry()) ^ (null == getArchiveEntry())) {
91       return false;
92       }
93
94       if (null != getArchiveEntry() ) {
95       return getArchiveEntry().getName().equals(other.getArchiveEntry().getName());
96       }
97       //@yury: added ArchiveEntry processing ]]]]]
98 */

99
100     //^olsen: simplify control flow
101
if (isZipped())
102       return (other.isZipped() &&
103           other.zipFile.getName().equals(zipFile.getName()));
104     else if (other.isZipped())
105       return false;
106     else if (other.classFile != null && classFile != null)
107       return other.classFile.getPath().equals(classFile.getPath());
108     //@olsen: added test
109
else if (byteCodeStream != null)
110       return byteCodeStream.equals(other.byteCodeStream);
111     return false;
112   }
113
114   /**
115    * Does this class originate in a zip file?
116    */

117   public boolean isZipped() {
118     return zipFile != null;
119   }
120
121   /**
122    * Does this class originate in a zip file?
123    */

124   //@olsen: added method
125
public boolean isStreamed() {
126     return byteCodeStream != null;
127   }
128
129   /**
130    * The expected name of the class contained in the class file.
131    * Returns null if the class name can not be intuited from the file name.
132    */

133   public String JavaDoc expectedClassName() {
134     return theExpectedClassName;
135   }
136
137   /**
138    * Set the name of the class contained in the class file.
139    */

140   public void setExpectedClassName(String JavaDoc name) {
141     theExpectedClassName = name;
142   }
143
144   /**
145    * Get the path of the File containing the class
146    */

147   public String JavaDoc containingFilePath() {
148     if (isZipped())
149       return zipFile.getName();
150     else if (classFile != null)
151       return classFile.getPath();
152     else
153       return null;
154   }
155
156   /**
157    * Constructor
158    * @param className The expected name of the class
159    * @param classFile The file containing the class. This file should
160    * exist and be readable.
161    */

162   public ClassFileSource(String JavaDoc className, File JavaDoc classFile) {
163     //@olsen: added println() for debugging
164
//System.out.println("ClassFileSource(): new class = " + className);
165
theExpectedClassName = className;
166     theOriginalExpectedClassName = className;
167     this.classFile = classFile;
168   }
169
170     //@yury: added archive entry-based constructor
171
/**
172      * Constructs the ClassFileSource form the ArchiveEntry
173      *
174      * @param className The class name
175      * @param entry The archive entry
176      */

177 /*
178     public ClassFileSource(String className, ArchiveEntry entry) {
179     archiveEntry = entry;
180     theExpectedClassName = className;
181     theOriginalExpectedClassName = className;
182     }
183 */

184
185   /**
186    * Constructor
187    * @param className The expected name of the class
188    * @param classFile The zip file containing the class. This file should
189    * exist and be readable.
190    */

191   public ClassFileSource(String JavaDoc className, ZipFile JavaDoc zipFile) {
192     //@olsen: added println() for debugging
193
//System.out.println("ClassFileSource(): new class = " + className);
194
theExpectedClassName = className;
195     theOriginalExpectedClassName = className;
196     this.zipFile = zipFile;
197   }
198
199   /**
200    * Constructor
201    * @param className The expected name of the class
202    * @param classFile The zip file containing the class. This file should
203    * exist and be readable.
204    */

205   //@olsen: added constructor
206
public ClassFileSource(String JavaDoc className, InputStream byteCodeStream) {
207     //@olsen: added println() for debugging
208
//System.out.println("ClassFileSource(): new class = " + className);
209
theExpectedClassName = className;
210     theOriginalExpectedClassName = className;
211     this.byteCodeStream = byteCodeStream;
212   }
213
214   /**
215    * Attempt to find the next possible source of the class
216    */

217   public ClassFileSource nextSource(String JavaDoc className) {
218     if (sourceElement != null && sourceElement.next() != null)
219       return ClassPath.findClass(className, sourceElement.next());
220     return null;
221   }
222
223   /**
224    * Build a "friend" source file specification for the class of
225    * the given name. That is, the new class file source should be
226    * in the same zip file if zipped or else the same directory.
227    *
228    * Restriction: containingFilePath() must be non-null.
229    */

230   public ClassFileSource friendSource(String JavaDoc className) {
231 /*
232       //@yury: ArchiveEntry case sanity check
233       if ( null != archiveEntry) {
234       throw new IllegalArgumentException("----- Not implemented yet");
235       }
236 */

237
238     if (isZipped())
239       return new ClassFileSource(className, zipFile);
240     else {
241       String JavaDoc fullPath = FilePath.getAbsolutePath(classFile);
242       File JavaDoc dir = new File JavaDoc(fullPath.substring(
243        0, fullPath.lastIndexOf(File.separatorChar)+1));
244       File JavaDoc f = new File JavaDoc(dir, unpackagedName(className) + ".class");//NOI18N
245
return new ClassFileSource(className, f);
246     }
247   }
248
249   /**
250    * Get a DataInputStream containing the class file.
251    *
252    * Restriction: containingFilePath() must be non-null.
253    */

254   public DataInputStream classFileContents()
255       throws IOException, FileNotFoundException {
256 /*
257       //@yury: ArchiveEntry case sanity check
258       if ( null != archiveEntry) {
259       return new DataInputStream(new BufferedInputStream(archiveEntry.createInputStream()));
260       }
261 */

262     //@olsen: cosmetics
263
if (isZipped()) {
264       ZipEntry JavaDoc entry =
265     zipFile.getEntry(ClassPath.zipFileNameOf(theExpectedClassName));
266       if (entry == null)
267     throw new FileNotFoundException(
268     "The zip file member " + theExpectedClassName + " was not found.");
269       return new DataInputStream(zipFile.getInputStream(entry));
270     }
271     //@olsen: added case
272
if (isStreamed()) {
273       return new DataInputStream(byteCodeStream);
274     }
275     return new DataInputStream(
276       new BufferedInputStream(
277     new FileInputStream(classFile)));
278   }
279
280   /**
281    * Get the modification date of the class file. The date format is
282    * that used by java.util.Date.
283    *
284    * Restriction: containingFilePath() must be non-null.
285    */

286   public long modificationDate() throws FileNotFoundException {
287     if (cachedModDate == 0) {
288 /*
289     //@yury: ArchiveEntry case sanity check
290     if ( null != archiveEntry) {
291         throw new IllegalArgumentException("----- Not implemented yet");
292     }
293 */

294
295       if (isZipped()) {
296     ZipEntry JavaDoc entry =
297       zipFile.getEntry(ClassPath.zipFileNameOf(theOriginalExpectedClassName));
298     if (entry == null)
299       throw new FileNotFoundException("The zip file member was not found.");
300     cachedModDate = entry.getTime();
301       }
302       else if (classFile != null)
303     cachedModDate = classFile.lastModified();
304     }
305
306     return cachedModDate;
307   }
308
309   /**
310    * Set the cached modification date of the class file.
311    * This doesn't actually update the file.
312    */

313   public void setModificationDate(long date) {
314     cachedModDate = date;
315   }
316
317   /**
318    * Set the ClassPathElement through which this was located
319    */

320   void setSourceElement(ClassPathElement cpathElement) {
321     sourceElement = cpathElement;
322   }
323
324   /**
325    * Compute the destination directory for the class.
326    * rootDestDir must be non-null - use that as a destination
327    * location root, ensuring its existence.
328    */

329   private File JavaDoc computeDestinationDir(File JavaDoc rootDestDir) throws IOException, FileNotFoundException {
330
331     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(rootDestDir.getPath());
332     String JavaDoc prevToken = null;
333     StringTokenizer parser
334         = new StringTokenizer(theExpectedClassName, "/", false);//NOI18N
335
while (parser.hasMoreTokens()) {
336       if (prevToken != null) {
337     buf.append(File.separatorChar);
338     buf.append(prevToken);
339
340     File JavaDoc currDir = new File JavaDoc(buf.toString());
341     if (!currDir.isDirectory()) {
342       if (!currDir.mkdir())
343             //@olsen: support for I18N
344
throw new UserException(
345                 getI18N("enhancer.unable_to_create_dir",//NOI18N
346
currDir.getPath()));
347     }
348       }
349       prevToken = parser.nextToken();
350     }
351     return new File JavaDoc(buf.toString());
352   }
353
354   /**
355    * Compute the destination file for the class.
356    * If destDir is non-null, use that as a destination location
357    *
358    * Restriction: if containingFilePath() is null, null is returned.
359    */

360   public File JavaDoc computeDestination(File JavaDoc destDir)
361       throws IOException, FileNotFoundException {
362       if (destDir != null) {
363     File JavaDoc finalDestDir = computeDestinationDir(destDir);
364     String JavaDoc theFinalClassComponent = "";//NOI18N
365
StringTokenizer parser =
366             new StringTokenizer(theExpectedClassName, "/", false);//NOI18N
367
while (parser.hasMoreTokens())
368       theFinalClassComponent = parser.nextToken();
369     return new File JavaDoc(finalDestDir, theFinalClassComponent + ".class");//NOI18N
370
}
371       else
372     /* Note: this is wrong when repackaging occurs but we currently
373        require a destination directory to be specified, so it doesn't
374        matter. */

375     return classFile;
376   }
377
378   /**
379    * Get a DataOutputStream to which a class file should be written.
380    * The caller must close the output stream when complete.
381    */

382   public DataOutputStream getOutputStream(File JavaDoc dest) throws IOException, FileNotFoundException {
383 /*
384       //@yury: ArchiveEntry case sanity check
385       if ( null != archiveEntry) {
386       throw new IllegalArgumentException("----- Must never call here");
387       }
388 */

389
390     /* If this were a zipped file we would need to do some fancy footwork */
391     return new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
392   }
393
394   /**
395    * Return the name of the class, ignoring any leading package specification.
396    */

397   private String JavaDoc unpackagedName(String JavaDoc className) {
398     int idx = className.lastIndexOf((int) '/');
399     if (idx < 0)
400       return className;
401     return className.substring(idx+1);
402   }
403 }
404
Popular Tags