KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > enhancer > Main


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;
26
27 //@olsen:
28
//import java.io.*;
29
import java.io.IOException JavaDoc;
30 import java.io.FileNotFoundException JavaDoc;
31 import java.io.File JavaDoc;
32 import java.io.InputStream JavaDoc;
33 import java.io.OutputStream JavaDoc;
34 import java.io.FileInputStream JavaDoc;
35 import java.io.FileOutputStream JavaDoc;
36 import java.io.DataInputStream JavaDoc;
37 import java.io.DataOutputStream JavaDoc;
38 import java.io.BufferedInputStream JavaDoc;
39 import java.io.BufferedOutputStream JavaDoc;
40 import java.io.PrintWriter JavaDoc;
41 import java.io.FileReader JavaDoc;
42 import java.io.BufferedReader JavaDoc;
43
44 //@olsen:
45
//import java.util.*;
46
import java.util.Map JavaDoc;
47 import java.util.Collection JavaDoc;
48 import java.util.Enumeration JavaDoc;
49 import java.util.Iterator JavaDoc;
50 import java.util.ArrayList JavaDoc;
51 import java.util.HashMap JavaDoc;
52 import java.util.Hashtable JavaDoc;
53 import java.util.Properties JavaDoc;
54 import java.util.StringTokenizer JavaDoc;
55
56 import java.util.zip.ZipFile JavaDoc;
57 import java.util.zip.ZipEntry JavaDoc;
58 import java.util.zip.ZipInputStream JavaDoc;
59 import java.util.zip.ZipOutputStream JavaDoc;
60 import java.util.zip.ZipException JavaDoc;
61
62 import java.net.URL JavaDoc;
63
64 import com.sun.jdo.api.persistence.model.Model;
65
66 //import com.sun.jdo.api.persistence.enhancer.util.ClassFileSource;
67
//import com.sun.jdo.api.persistence.enhancer.util.ZipFileRegistry;
68
//import com.sun.jdo.api.persistence.enhancer.util.ClassPath;
69
//import com.sun.jdo.api.persistence.enhancer.util.FilePath;
70

71 //@olsen: added support for timing statistics
72
import com.sun.jdo.api.persistence.enhancer.util.Support;
73
74 //import com.sun.jdo.api.persistence.enhancer.classfile.ClassFile;
75

76 import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaData;
77 import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaDataModelImpl;
78 import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaDataPropertyImpl;
79 import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaDataTimer;
80
81 //import com.sun.jdo.api.persistence.enhancer.impl.ClassControl;
82
//import com.sun.jdo.api.persistence.enhancer.impl.Environment;
83

84
85 //import org.openidex.jarpackager.ArchiveEntry; //@yury Added the capability to create ClassFileSources out of ArchiveEntries
86

87 //@olsen: disabled feature
88
/*
89 import com.sun.jdo.api.persistence.enhancer.impl.FieldMap;
90 */

91
92 //@lars: moved functionality into ByteCodeEnhancerHelper
93
//@lars: design improvements
94
//@olsen: cosmetics
95
//@olsen: subst: [iI]Persistent -> [pP]ersistenceCapable
96
//@olsen: subst: /* ... */ -> // ...
97
//@olsen: moved: class FilterError -> package util
98
//@olsen: moved: OSCFP.addClass(ClassControl) -> impl.Environment
99
//@olsen: subst: filterEnv.classMap.elements() -> filterEnv.getClasses()
100
//@olsen: subst: filterEnv.classMap.get(name) -> filterEnv.getClass(name)
101
//@olsen: subst: filterEnv.translations -> filterEnv.translations()
102
//@olsen: subst: filterEnv.translations -> filterEnv.destinationDirectory()
103
//@olsen: subst: OSCFP -> Main
104
//@olsen: subst: filterEnv -> env
105
//@olsen: subst: FilterEnv -> Environment
106
//@olsen: dropped parameter 'Environment env', use association instead
107
//@olsen: subst: augment -> closeOver
108
//@olsen: subst: collectAllClasses -> collectClasses
109
//@olsen: subst: Vector -> Collection, List, ArrayList
110
//@olsen: subst: Hashtable -> Map, HashMap
111
//@olsen: subst: Enumeration,... -> Iterator, hasNext(), next()
112
//@olsen: moved: Main.closeOverClasses() -> EnhancerControl
113
//@olsen: moved: Main.closeOverClass(ClassControl) -> EnhancerControl
114
//@olsen: moved: Main.modifyClasses() -> EnhancerControl
115
//@olsen: moved: Main.retargetClasses() -> EnhancerControl
116
//@olsen: moved: Main.locateTranslatedClasses() -> EnhancerControl
117
//@olsen: moved: Main.checkIndexableFields() -> EnhancerControl
118
//@olsen: subst: (ClassControl) control -> cc
119
//@olsen: removed: proprietary support for HashCode
120
//@olsen: removed: proprietary support for TypeSummary
121
//@olsen: removed: proprietary support for ClassInfo
122
//@olsen: removed: proprietary support for IndexableField
123
//@olsen: removed: support for IgnoreTransientField, AddedTransientField
124
//@olsen: removed: support for [No]AnnotateField
125

126
127 /**
128  * Main is the starting point for the persistent filter tool.
129  */

130 public class Main
131 {
132
133
134     /**
135      * The byte code enhancer.
136      */

137     private ByteCodeEnhancer enhancer = null;
138
139
140     /**
141      * The stream to write messages to.
142      */

143     private final PrintWriter JavaDoc outMessages = new PrintWriter JavaDoc (System.out, true);
144
145
146     /**
147      * The stream to write error messages to.
148      */

149     private final PrintWriter JavaDoc outErrors = new PrintWriter JavaDoc (System.err, true);
150
151
152     /**
153      * The command line options.
154      */

155     private final CmdLineOptions cmdLineOpts = new CmdLineOptions ();
156
157
158     /**
159      * Construct a filter tool instance
160      */

161     public Main() {
162     }
163
164
165     /**
166      * This is where it all starts.
167      */

168     public static void main(String JavaDoc[] argv) {
169         //@olsen: added support for timing statistics
170
final Main main = new Main();
171         try {
172             //@olsen: split: method filter() -> process(), processArgs()
173
//System.exit(new Main().process(argv));
174
main.process(argv);
175         } catch (RuntimeException JavaDoc tt) {
176             //} catch (Throwable tt) {
177
//@olsen: changed to print to error stream
178
System.err.println("Exception occurred while postprocessing:");
179             tt.printStackTrace(System.err);
180             //System.exit(1);
181
throw tt;
182         } finally {
183             //@olsen: added support for timing statistics
184
if (main.cmdLineOpts.doTiming) {
185                 Support.timer.print();
186             }
187         }
188     }
189
190     /**
191      * Process command line options and perform filtering tasks
192      */

193     //@olsen: split: method filter() -> process(), processArgs()
194
public int process(String JavaDoc[] argv) {
195         //@olsen: added inplace of disabled feature
196
ArrayList JavaDoc cNames = new ArrayList JavaDoc();
197         //@olsen: split: method filter() -> process(), processArgs()
198
int res = processArgs(argv, cNames);
199         if (res != 0) {
200             //@olsen: added println()
201
printMessage ("aborted with errors.");//NOI18N
202
return res;
203         }
204
205         //@olsen: added support for timing statistics
206
try {
207             if (this.cmdLineOpts.doTiming) {
208                 Support.timer.push("Main.process(String[])");//NOI18N
209
}
210
211             // Find all of the classes on which we want to operate
212
//@olsen: disabled feature
213
enhanceInputFiles (cNames);
214 /*
215             computeClasses(pcNames, paNames, ccNames);
216 */

217
218             printMessage ("done.");//NOI18N
219
return 0;
220         } finally {
221             if (this.cmdLineOpts.doTiming) {
222                 Support.timer.pop();
223             }
224         }
225     }
226
227     /**
228      * Process command line options
229      */

230     //@olsen: split: method filter() -> process(), processArgs()
231
//@olsen: made private
232
protected int processArgs(String JavaDoc[] argv,
233                             //@olsen: added inplace of disabled feature
234
Collection JavaDoc cNames) {
235         argv = preprocess(argv);
236
237 //@olsen: disabled feature
238
/*
239         ArrayList ccNames = new ArrayList();
240         ArrayList pcNames = new ArrayList();
241         ArrayList paNames = new ArrayList();
242         int classMode = ClassControl.PersistCapable;
243 */

244
245 //@olsen: disabled feature
246
/*
247         String classpath = System.getProperty("java.class.path");
248         String sysClasspath = System.getProperty("sun.boot.class.path", "");
249 */

250
251         //@olsen: added
252
Properties JavaDoc jdoMetaDataProperties = null;
253
254         for (int i=0; i<argv.length; i++) {
255             //@olsen: improved control flow, subst: else -> continue
256

257             String JavaDoc arg = argv[i];
258 //@olsen: disabled feature
259
/*
260             if (arg.equals("-cc") ||
261                 arg.equals("-copyclass")) {
262                 classMode = ClassControl.PersistUnknown;
263                 continue;
264             }
265             if (arg.equals("-pa") ||
266                 arg.equals("-persistaware")) {
267                 classMode = ClassControl.PersistAware;
268                 continue;
269             }
270             if (arg.equals("-pc") ||
271                 arg.equals("-persistcapable")) {
272                 classMode = ClassControl.PersistCapable;
273                 continue;
274             }
275 */

276             if (arg.equals("-v") ||//NOI18N
277
arg.equals("-verbose")) {//NOI18N
278
this.cmdLineOpts.verbose = true;
279                 this.cmdLineOpts.quiet = false;
280                 continue;
281             }
282             if (arg.equals("-q") ||//NOI18N
283
arg.equals("-quiet")) {//NOI18N
284
this.cmdLineOpts.quiet = true;
285                 this.cmdLineOpts.verbose = false;
286                 continue;
287             }
288             if (arg.equals("-f") ||//NOI18N
289
arg.equals("-force")) {//NOI18N
290
this.cmdLineOpts.forceWrite = true;
291                 continue;
292             }
293 //@olsen: disabled feature
294
/*
295             if (arg.equals("-inplace")) {
296                 env.setUpdateInPlace(true);
297                 continue;
298             }
299 */

300 //@lars: disabled feature
301
/*
302             if (arg.equals("-qf") ||//NOI18N
303                 arg.equals("-quietfield")) {//NOI18N
304                 if (argv.length-i < 2) {
305                     usage();
306                     printError ("Missing argument to the -quietfield option", null);//NOI18N
307                 } else {
308                     String fullFieldName = argv[++i];
309                     if (fullFieldName.indexOf('.') == -1) {
310                         printError ("Field name specifications must include " +//NOI18N
311                                   "a fully qualified class name. " +//NOI18N
312                                   fullFieldName + " does not include one.", null);//NOI18N
313                     } else {
314                         env.suppressFieldWarnings(fullFieldName);
315                     }
316                 }
317                 continue;
318             }
319             if (arg.equals("-qc") ||//NOI18N
320                 arg.equals("-quietclass")) {//NOI18N
321                 if (argv.length-i < 2) {
322                     usage();
323                     env.error("Missing argument to the -quietclass option");//NOI18N
324                 } else {
325                     env.suppressClassWarnings(argv[++i]);
326                 }
327                 continue;
328             }
329 */

330             if (arg.equals("-nowrite")) {//NOI18N
331
this.cmdLineOpts.noWrite = true;
332                 continue;
333             }
334 //@olsen: disabled feature
335
/*
336             if (arg.equals("-modifyjava")) {
337                 env.setModifyJavaClasses(true);
338                 continue;
339             }
340 */

341 //@olsen: disabled feature
342
/*
343             if (arg.equals("-modifyfinals")) {
344                 env.setAllowFinalModifications(true);
345                 continue;
346             }
347 */

348 //@olsen: disabled feature
349
/*
350             if (arg.equals("-noarrayopt")) {
351                 env.setNoArrayOptimization(true);
352                 continue;
353             }
354 */

355 //@lars: disabled feature
356
/*
357             if (arg.equals("-nothisopt")) {//NOI18N
358                 env.setNoThisOptimization(true);
359                 continue;
360             }
361             if (arg.equals("-noinitializeropt")) {//NOI18N
362                 env.setNoInitializerOptimization(true);
363                 continue;
364             }
365             if (arg.equals("-noopt")) {//NOI18N
366                 env.setNoOptimization(true);
367                 continue;
368             }
369 */

370             if (arg.equals("-d") ||//NOI18N
371
arg.equals("-dest")) {//NOI18N
372
if (argv.length-i < 2) {
373                     printError ("Missing argument to the -dest option", null);//NOI18N
374
usage();
375                 }
376                 this.cmdLineOpts.destinationDirectory = argv[++i];
377                 continue;
378             }
379 //@olsen: disabled feature
380
/*
381             if (arg.equals("-classpath") ||
382                 arg.equals("-cpath")) {
383                 if (argv.length-i < 2) {
384                     usage();
385                     env.error("Missing argument to the -classpath option");
386                 }
387                 classpath = argv[++i];
388                 continue;
389             }
390             if (arg.equals("-sysclasspath") ||
391                 arg.equals("-syscpath")) {
392                 if (argv.length-i < 2) {
393                     usage();
394                     env.error("Missing argument to the -sysclasspath option");
395                 }
396                 sysClasspath = argv[++i];
397                 continue;
398             }
399 */

400 //@olsen: disabled feature
401
/*
402             if (arg.equals("-tp") ||
403                 arg.equals("-translatepackage")) {
404                 if (argv.length-i < 3) {
405                     usage();
406                     env.error("Missing arguments to the -translatepackage option");
407                 }
408                 env.setPackageTranslation(argv[i+1], argv[i+2]);
409                 i += 2;
410                 continue;
411             }
412 */

413             //@olsen: new command line option for timing statistics
414
if (arg.equals("-t") ||//NOI18N
415
arg.equals("--doTiming")) {//NOI18N
416
this.cmdLineOpts.doTiming = true;
417 // env.setDoTimingStatistics(true);
418
continue;
419             }
420             //@olsen: new command line option for JDO meta data properties
421
if (arg.equals("-jp") ||//NOI18N
422
arg.equals("--jdoProperties")) {//NOI18N
423
if (argv.length-i < 2) {
424                     printError("Missing argument to the -jp/--jdoProperties option", null);//NOI18N
425
usage();
426                 }
427                 try {
428                     jdoMetaDataProperties = new Properties JavaDoc();
429                     jdoMetaDataProperties.load(new FileInputStream JavaDoc(argv[++i]));
430                 } catch (IOException JavaDoc ex) {
431                     printError("Cannot read JDO meta data properties from file", ex);//NOI18N
432
usage();
433                 }
434                 continue;
435             }
436             if (arg.length() > 0 && arg.charAt(0) == '-') {
437                 printError("Unrecognized option:" + arg, null);//NOI18N
438
usage();
439             }
440             if (arg.length() == 0) {
441                 printMessage ("Empty file name encountered on the command line.");//NOI18N
442
}
443
444             //@olsen: added inplace of disabled feature
445
cNames.add(arg);
446 //@olsen: disabled feature
447
/*
448             {
449                 if (arg.equals("java.lang.Object"))
450                     env.error("java.lang.Object may not be postprocessed");
451                 else if (classMode == ClassControl.PersistCapable)
452                     pcNames.add(arg);
453                 else if (classMode == ClassControl.PersistAware)
454                     paNames.add(arg);
455                 else if (classMode == ClassControl.PersistUnknown)
456                     ccNames.add(arg);
457                 else
458                     affirm(false, "Invalid class mode");
459             }
460 */

461         }
462
463         //@olsen: forced settings
464
//env.setVerbose(true);
465
this.cmdLineOpts.quiet = false;
466 // env.setNoOptimization(true);
467
// env.message("forced settings: -noopt");//NOI18N
468

469 /*
470         if (env.errorCount() > 0)
471             return 1;
472 */

473
474 //@olsen: disabled feature
475
/*
476         env.setClassPath(classpath +
477                          java.io.File.pathSeparator +
478                          sysClasspath);
479 */

480
481         // The user must specify a destination directory
482
if (this.cmdLineOpts.destinationDirectory == null) {
483             if (argv.length > 0)
484                 printError("No -dest output directory was specified", null);//NOI18N
485
usage();
486         }
487
488         //@olsen: added: initialize JDO meta data
489
JDOMetaData jdoMetaData;
490         if (jdoMetaDataProperties != null) {
491             printMessage("using JDO meta-data from properties");//NOI18N
492
jdoMetaData = new JDOMetaDataPropertyImpl(jdoMetaDataProperties, this.outMessages);
493         } else {
494             printMessage("using JDO meta-data from Model.Enhancer");//NOI18N
495
jdoMetaData = new JDOMetaDataModelImpl(Model.ENHANCER, this.outMessages);
496         }
497         //@olsen: added support for timing statistics
498
if (this.cmdLineOpts.doTiming) {
499             // wrap with timing meta data object
500
jdoMetaData = new JDOMetaDataTimer(jdoMetaData);
501         }
502
503         try
504         {
505             this.enhancer = createEnhancer (jdoMetaData);
506         }
507         catch (Exception JavaDoc ex)
508         {
509             printError ("Error creating the enhancer", ex);
510         }
511
512
513 //@olsen: disabled feature
514
/*
515         // -translatepackage is incompatible with in-place update.
516         if (env.updateInPlace() && env.translations().size() > 0) {
517             env.error("The -translatepackage option cannot be used " +
518                       "in conjunction with the -inplace option.");
519             return 1;
520         }
521 */

522
523         // make sure we don't lookup classes from the destination directory
524
// unless we are doing in-place annotation, and in that case it should
525
// be as a last resort.
526
//@lars: removed
527
/*
528         if (env.updateInPlace())
529             env.moveDestinationDirectoryToEnd();
530         else
531             env.excludeDestinationDirectory();
532 */

533
534         //@olsen: split: method filter() -> process(), processArgs()
535
return 0;
536     }
537
538     // Private methods
539

540     /**
541      * Preprocess @files, returning a new argv incorporating the contents
542      * of the @files, if any
543      */

544     private String JavaDoc[] preprocess(String JavaDoc[] args) {
545         ArrayList JavaDoc argVec = new ArrayList JavaDoc();
546         for (int i=0; i<args.length; i++) {
547             if (args[i].length() > 0 && args[i].charAt(0) == '@') {
548                 String JavaDoc filename = null;
549                 if (args[i].length() == 1) {
550                     if (i+1 < args.length)
551                         filename = args[++i];
552                 } else {
553                     filename = args[i].substring(1);
554                 }
555
556                 if (filename == null) {
557                     printError("missing file name argument to @.", null);//NOI18N
558
} else {
559                     appendFileContents(filename, argVec);
560                 }
561             } else {
562                 argVec.add(args[i]);
563             }
564         }
565         //@olsen: subst: Vector -> ArrayList
566
//String[] newArgs = new String[argVec.size()];
567
//argVec.copyInto(newArgs);
568
final String JavaDoc[] newArgs = (String JavaDoc[])argVec.toArray(new String JavaDoc[0]);
569         return newArgs;
570     }
571
572     /**
573      * Given an input file name, open the file and append each "word"
574      * within the file to argVec. This currently has only a very
575      * primitive notion of words (separated by white space).
576      */

577     private void appendFileContents(String JavaDoc filename, ArrayList JavaDoc argVec) {
578         try {
579             FileReader JavaDoc inputFile = new FileReader JavaDoc(filename);
580             try {
581                 BufferedReader JavaDoc input = new BufferedReader JavaDoc(inputFile);
582                 String JavaDoc s = null;
583                 while ((s = input.readLine()) != null) {
584                     StringTokenizer JavaDoc parser = new StringTokenizer JavaDoc(s, " \t", false);//NOI18N
585
while (parser.hasMoreElements()) {
586                         String JavaDoc token = parser.nextToken();
587                         if (token.length() > 0 && token.charAt(0) == '@')
588                             printError("The included file \"" +//NOI18N
589
filename +
590                                       "\" contains a recursive include. " +//NOI18N
591
"Recursive includes are not supported.", null);//NOI18N
592
if (token.charAt(0) == '#') break;
593                         argVec.add(token);
594                     }
595                 }
596             }
597             catch (IOException JavaDoc ex) {
598                 printError("IO exception reading file " + filename + ".", ex);//NOI18N
599
}
600         }
601         catch (FileNotFoundException JavaDoc ex) {
602             printError("file " + filename + " not found.", ex);//NOI18N
603
}
604     }
605
606
607     /**********************************************************************
608      *
609      *********************************************************************/

610
611     private final ByteCodeEnhancer createEnhancer (JDOMetaData jdometadata)
612                                    throws EnhancerUserException,
613                                           EnhancerFatalError
614     {
615
616         Properties JavaDoc props = new Properties JavaDoc ();
617         if (this.cmdLineOpts.verbose)
618         {
619             props.put (FilterEnhancer.VERBOSE_LEVEL, FilterEnhancer.VERBOSE_LEVEL_VERBOSE);
620         }
621
622         return new FilterEnhancer (jdometadata, props, this.outMessages, this.outErrors);
623
624     } //Main.createEnhancer()
625

626
627     /**********************************************************************
628      * Enhances all files entered in the command line.
629      *
630      * @param filenames The filenames.
631      *********************************************************************/

632
633     private final void enhanceInputFiles (Collection JavaDoc filenames)
634     {
635
636         for (Iterator JavaDoc names = filenames.iterator(); names.hasNext ();)
637         {
638             try
639             {
640                 String JavaDoc name = (String JavaDoc) names.next ();
641                 int n = name.length ();
642
643                 //if we have a class-files
644
InputStream JavaDoc in = null;
645                 if (isClassFileName (name))
646                 {
647                     enhanceClassFile (openFileInputStream (name));
648                 }
649                 else
650                 {
651                     //if we have an archive
652
if (isZipFileName (name))
653                     {
654                         enhanceZipFile (name); //getZipFile (name));
655
}
656                     //assume that it is a class name
657
else
658                     {
659                         enhanceClassFile (openClassInputStream (name));
660                     }
661                 }
662             }
663             catch (Throwable JavaDoc ex)
664             {
665                 printError (null, ex);
666             }
667         }
668
669     } //Main.enhanceInputFiles()
670

671
672     /**********************************************************************
673      * Enhances a classfile.
674      *
675      * @param in The input stream of the classfile.
676      *********************************************************************/

677
678     private final void enhanceClassFile (InputStream JavaDoc in)
679     {
680
681         OutputStream JavaDoc out = null;
682         try
683         {
684             File JavaDoc temp = File.createTempFile ("enhancer", ".class");
685             out = new BufferedOutputStream JavaDoc (new FileOutputStream JavaDoc (temp));
686
687             //enhance
688
OutputStreamWrapper wrapper = new OutputStreamWrapper (out);
689             boolean enhanced = this.enhancer.enhanceClassFile (in, wrapper);
690             closeOutputStream (out);
691             createOutputFile (enhanced, createClassFileName (wrapper.getClassName ()), temp);
692         }
693         catch (Throwable JavaDoc ex)
694         {
695             printError (null, ex);
696         }
697         finally
698         {
699             closeInputStream (in);
700             closeOutputStream (out);
701         }
702
703     } //Main.enhanceClassFile()
704

705
706     /**********************************************************************
707      * Enhances a zipfile.
708      *
709      * @param name The filename of the zipfile.
710      *********************************************************************/

711
712     private final void enhanceZipFile (String JavaDoc filename)
713     {
714
715         ZipInputStream JavaDoc in = null;
716         ZipOutputStream JavaDoc out = null;
717         try
718         {
719             File JavaDoc temp = File.createTempFile ("enhancer", ".zip");
720             in = new ZipInputStream JavaDoc (new BufferedInputStream JavaDoc (new FileInputStream JavaDoc (new File JavaDoc (filename))));
721             out = new ZipOutputStream JavaDoc (new BufferedOutputStream JavaDoc (new FileOutputStream JavaDoc (temp)));
722
723             //enhance the zipfile
724
boolean enhanced = ByteCodeEnhancerHelper.enhanceZipFile (this.enhancer, in, out);
725             closeOutputStream (out);
726             out = null;
727
728             //create the output file
729
createOutputFile (enhanced, new File JavaDoc (filename).getName (), temp);
730         }
731         catch (Throwable JavaDoc ex)
732         {
733             printError (null, ex);
734         }
735         finally
736         {
737             closeOutputStream (out);
738             closeInputStream (in);
739         }
740
741     } //Main.enhanceZipFile()
742

743
744     /**********************************************************************
745      * Opens an input stream for the given filename
746      *
747      * @param filename The name of the file.
748      *
749      * @return The input stream.
750      *
751      * @exception FileNotFoundException If the file could not be found.
752      *********************************************************************/

753
754     private static final InputStream JavaDoc openFileInputStream (String JavaDoc filename)
755                                      throws FileNotFoundException JavaDoc
756     {
757
758         return new BufferedInputStream JavaDoc (new FileInputStream JavaDoc (new File JavaDoc (filename)));
759
760     } //Main.openFileInputStream()
761

762
763     /**********************************************************************
764      * Opens an input stream for the given classname. The input stream is
765      * created via an URL that is obtained by the current ClassLoader.
766      *
767      * @param classname The name of the class (dot-notation).
768      *
769      * @return The iput stream.
770      *
771      * @exception IOException If an I/O error occured.
772      * @exception ClassNotFoundException If the class could not be found.
773      *********************************************************************/

774
775     private final InputStream JavaDoc openClassInputStream (String JavaDoc classname)
776                               throws IOException JavaDoc,
777                                      ClassNotFoundException JavaDoc
778     {
779
780         URL JavaDoc url = Main.class.getClassLoader ().getSystemResource (createClassFileName (classname));
781         if (url == null)
782         {
783             throw new ClassNotFoundException JavaDoc (classname);
784         }
785         return url.openStream ();
786
787     } //Main.getClassInPath()
788

789
790     /**********************************************************************
791      * Tests if a filename is a classfile name.
792      *
793      * @param filename The name of the file.
794      *
795      * @return Do we have a potential classfile?
796      *********************************************************************/

797
798     private static final boolean isClassFileName (String JavaDoc filename)
799     {
800
801         return filename.endsWith (".class");
802
803     } //Main.isClassFileName()
804

805
806     /**********************************************************************
807      * Tests if a filename is a zipfile (only by testing if the extension -
808      * ignoring the case - is <code>".zip"</code> or <code>".jar"</code>).
809      *
810      * @param filename The name of the file.
811      *
812      * @param Do we have a potential zipfile?
813      *********************************************************************/

814
815     private static final boolean isZipFileName (String JavaDoc filename)
816     {
817
818         final int n = filename.length ();
819         if (n < 5)
820         {
821             return false;
822         }
823         String JavaDoc ext = filename.substring (n - 4);
824
825         return ext.equalsIgnoreCase (".zip") || ext.equalsIgnoreCase (".jar");
826
827     } //Main.isZipFileName
828

829
830     /**********************************************************************
831      * Creates a filename from a classname (by replacing <code>'.'</code>
832      * by <code>'/'</code>.
833      *
834      * @param classname The classname.
835      *
836      * @return The filename.
837      *********************************************************************/

838
839     private static final String JavaDoc createClassFileName (String JavaDoc classname)
840     {
841
842         return classname.replace ('.', '/') + ".class";
843
844     } //Main.createClassFileName()
845

846
847     /**********************************************************************
848      * Creates a file object that represents the output zipfile for a given
849      * zipfile to enhance.
850      *
851      * @param zipfilename The input zipfile name.
852      *
853      * @return The output zipfile name.
854      *********************************************************************/

855
856     private final File JavaDoc createZipOutputFile (String JavaDoc zipfilename)
857     {
858
859         return new File JavaDoc (this.cmdLineOpts.destinationDirectory, new File JavaDoc (zipfilename).getName ());
860
861     } //Main.createZipOutputFile()
862

863
864     /**********************************************************************
865      * Creates the output file for an enhaced class- or zipfile. If the
866      * enhanced file is written back depends on the command line options.
867      *
868      * @param enhanced Has the input file been enhanced?
869      * @param filename The name of the output file.
870      * @param temp The temp file, the output is written to.
871      *
872      * @exception IOException If the file could not be created.
873      *********************************************************************/

874
875     private final void createOutputFile (boolean enhanced,
876                                          String JavaDoc filename,
877                                          File JavaDoc temp)
878                        throws IOException JavaDoc
879     {
880
881         //noWrite or (not enhanced and not forceWrite)
882
if (this.cmdLineOpts.noWrite || ( ! enhanced && ! this.cmdLineOpts.forceWrite))
883         {
884             temp.deleteOnExit ();
885             return;
886         }
887
888         File JavaDoc file = new File JavaDoc (this.cmdLineOpts.destinationDirectory, filename);
889         createPathOfFile (file);
890         file.delete (); //delete old file if exists
891
//@olsen: added workaround to JDK bug with file.renameTo()
892
boolean renamed = temp.renameTo(file);
893         if (!renamed) {
894             //@dave: empirical evidence shows that renameTo does not allow for
895
// crossing filesystem boundaries. If it fails, try "by hand".
896
try {
897                 DataInputStream JavaDoc dis =
898                     new DataInputStream JavaDoc(new FileInputStream JavaDoc(temp));
899                 DataOutputStream JavaDoc dos =
900                     new DataOutputStream JavaDoc(new FileOutputStream JavaDoc(file));
901                 int PAGESIZE = 4096; // Suggest a better size?
902
byte data[] = new byte[PAGESIZE];
903                 while (dis.available() > 0) {
904                     int numRead = dis.read(data, 0, PAGESIZE);
905                     dos.write(data, 0, numRead);
906                 }
907                 renamed = true;
908                 temp.delete (); // delete temp file
909
} catch (IOException JavaDoc ex) {
910                 // empty
911
}
912             if (!renamed) {
913                 throw new IOException JavaDoc("Could not rename temp file '" +
914                                       temp.getAbsolutePath() +
915                                       "' to '" + file.getAbsolutePath() + "'.");
916             }
917         }
918     }
919
920
921     /**********************************************************************
922      * Closes an input stream.
923      *
924      * @param in The input stream.
925      *********************************************************************/

926
927     private final void closeInputStream (InputStream JavaDoc in)
928     {
929
930         if (in != null)
931         {
932             try
933             {
934                 in.close ();
935             }
936             catch (IOException JavaDoc ex)
937             {
938                 printError (null, ex);
939             }
940         }
941
942     } //Main.closeInputStream()
943

944
945     /**********************************************************************
946      * Closes an output stream.
947      *
948      * @param in The output stream.
949      *********************************************************************/

950
951     private final void closeOutputStream (OutputStream JavaDoc out)
952     {
953
954         if (out != null)
955         {
956             try
957             {
958                 out.close ();
959             }
960             catch (IOException JavaDoc ex)
961             {
962                 printError (null, ex);
963             }
964         }
965
966     } //Main.closeOutputStream()
967

968
969     /**********************************************************************
970      * Creates only the path of the given file.
971      *
972      * @param file The file.
973      *
974      * @exception IOException If an error occured.
975      *********************************************************************/

976
977     private static final void createPathOfFile (File JavaDoc file)
978                               throws IOException JavaDoc
979     {
980
981         //Verzeichnis erzeugen
982
File JavaDoc dir = file.getAbsoluteFile ().getParentFile ();
983         if ( ! dir.exists () && ! dir.mkdirs ())
984         {
985             throw new IOException JavaDoc ("Error creating directory '" + dir.getAbsolutePath () + "'.");
986         }
987
988     } //Main.createPathOfFile()
989

990
991     /**********************************************************************
992      * Prints out an error.
993      *
994      * @param msg The error message (can be <code>null</code>).
995      * @param ex An optional exception (can be <code>null</code>).
996      *********************************************************************/

997
998     private final void printError (String JavaDoc msg,
999                                    Throwable JavaDoc ex)
1000    {
1001
1002        if (msg != null)
1003        {
1004            this.outErrors.println (msg + (ex != null ? ": " + ex : ""));
1005        }
1006        if (ex != null)
1007        {
1008            ex.printStackTrace (this.outErrors);
1009        }
1010
1011    } //Main.printError()
1012

1013
1014    /**********************************************************************
1015     * Prints out a message.
1016     *
1017     * @param msg The message.
1018     *********************************************************************/

1019
1020    private final void printMessage (String JavaDoc msg)
1021    {
1022
1023        this.outMessages.println (msg);
1024
1025    } //Main.printMessage()
1026

1027
1028    /**
1029     * Print a usage message to System.err
1030     */

1031    public static void usage() {
1032        //@olsen: document that main() takes a file name argument
1033
System.err.println("Usage: main <options> <file name>");
1034//@olsen: disabled feature
1035
/*
1036        System.err.println(" { -copyclass | -cc }");
1037        System.err.println(" { -persistaware | -pa }");
1038        System.err.println(" { -persistcapable | -pc }");
1039*/

1040        System.err.println(" { -verbose | -v }");
1041        System.err.println(" { -force | -f }");
1042        System.err.println(" { -quiet | -q }");
1043// System.err.println(" { -quietfield | -qf } <qualified field name>");
1044
// System.err.println(" { -quietclass | -qc } <qualified class name>");
1045
//@olsen: disabled feature
1046
/*
1047        System.err.println(" -inplace");
1048*/

1049// System.err.println(" -noarrayopt");
1050
// System.err.println(" -nothisopt");
1051
// System.err.println(" -noinitializeropt");
1052
// System.err.println(" -noopt");
1053
//@olsen: disabled feature
1054
/*
1055        System.err.println(" -modifyjava");
1056*/

1057//@olsen: disabled feature
1058
/*
1059        //@olsen: added missing cmd line option
1060        System.err.println(" -modifyfinals");
1061*/

1062        System.err.println(" -nowrite");
1063        System.err.println(" -dest | -d <destination directory>");
1064//@olsen: disabled feature
1065
/*
1066        System.err.println(" { -translatepackage | -tp } <orig pkg name> <new pkg name>");
1067*/

1068//@olsen: disabled feature
1069
/*
1070        System.err.println(" { -arraydims | -a } <number of array dimensions>");
1071*/

1072//@olsen: disabled feature
1073
/*
1074        System.err.println(" { -classpath | -cpath } <classpath for lookup>");
1075        System.err.println(" { -sysclasspath | -syscpath } <system classpath for lookup>");
1076*/

1077        //@olsen: new command line option for JDO meta data properties
1078
System.err.println(" --jdoProperties | -jp");
1079        System.err.println(" --timing | -t");
1080
1081        System.err.println(" @<cmd-arg-file>");
1082
1083        System.exit (1);
1084    }
1085
1086
1087    //#####################################################################
1088
/**
1089     * A class for holding the command line options.
1090     */

1091    //#####################################################################
1092

1093    private final class CmdLineOptions
1094    {
1095
1096
1097        /**
1098         * The destination directory to write the enhanced classes to.
1099         */

1100        String JavaDoc destinationDirectory = null;
1101
1102
1103        /**
1104         * Do timing messures?
1105         */

1106        boolean doTiming = false;
1107
1108
1109        /**
1110         * Verbose output?
1111         */

1112        boolean verbose = false;
1113
1114
1115        /**
1116         * No output at all?
1117         */

1118        boolean quiet = false;
1119
1120
1121        /**
1122         * Force a write even if the classfile has not been enhanced?
1123         */

1124        boolean forceWrite = false;
1125
1126
1127        /**
1128         * Really write the enhanced or not enhanced classes to disk?
1129         */

1130        boolean noWrite = false;
1131
1132
1133    } //CmdLineOptions
1134

1135
1136} //Main
1137
Popular Tags