KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > OutputWriter


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21 package proguard;
22
23 import proguard.classfile.ClassPool;
24 import proguard.io.*;
25 import proguard.util.FileNameListMatcher;
26
27 import java.io.IOException JavaDoc;
28
29 /**
30  * This class writes the output class files.
31  *
32  * @author Eric Lafortune
33  */

34 public class OutputWriter
35 {
36     private Configuration configuration;
37
38
39     /**
40      * Creates a new OutputWriter to write output class files as specified by
41      * the given configuration.
42      */

43     public OutputWriter(Configuration configuration)
44     {
45         this.configuration = configuration;
46     }
47
48
49     /**
50      * Writes the given class pool to class files, based on the current
51      * configuration.
52      */

53     public void execute(ClassPool programClassPool) throws IOException JavaDoc
54     {
55         ClassPath programJars = configuration.programJars;
56
57         // Perform a check on the first jar.
58
ClassPathEntry firstEntry = programJars.get(0);
59         if (firstEntry.isOutput())
60         {
61             throw new IOException JavaDoc("The output jar [" + firstEntry.getName() +
62                                   "] must be specified after an input jar, or it will be empty.");
63         }
64
65         // Perform some checks on the output jars.
66
for (int index = 0; index < programJars.size() - 1; index++)
67         {
68             ClassPathEntry entry = programJars.get(index);
69             if (entry.isOutput())
70             {
71                 // Check if all but the last output jars have filters.
72
if (entry.getFilter() == null &&
73                     entry.getJarFilter() == null &&
74                     entry.getWarFilter() == null &&
75                     entry.getEarFilter() == null &&
76                     entry.getZipFilter() == null &&
77                     programJars.get(index + 1).isOutput())
78                 {
79                     throw new IOException JavaDoc("The output jar [" + entry.getName() +
80                                           "] must have a filter, or all subsequent jars will be empty.");
81                 }
82
83                 // Check if the output jar name is different from the input jar names.
84
for (int inIndex = 0; inIndex < programJars.size(); inIndex++)
85                 {
86                     ClassPathEntry otherEntry = programJars.get(inIndex);
87
88                     if (!otherEntry.isOutput() &&
89                         entry.getFile().equals(otherEntry.getFile()))
90                     {
91                         throw new IOException JavaDoc("The output jar [" + entry.getName() +
92                                               "] must be different from all input jars.");
93                     }
94                 }
95             }
96         }
97
98         int firstInputIndex = 0;
99         int lastInputIndex = 0;
100
101         // Go over all program class path entries.
102
for (int index = 0; index < programJars.size(); index++)
103         {
104             // Is it an input entry?
105
ClassPathEntry entry = programJars.get(index);
106             if (!entry.isOutput())
107             {
108                 // Remember the index of the last input entry.
109
lastInputIndex = index;
110             }
111             else
112             {
113                 // Check if this the last output entry in a series.
114
int nextIndex = index + 1;
115                 if (nextIndex == programJars.size() ||
116                     !programJars.get(nextIndex).isOutput())
117                 {
118                     // Write the processed input entries to the output entries.
119
writeOutput(programClassPool,
120                                 programJars,
121                                 firstInputIndex,
122                                 lastInputIndex + 1,
123                                 nextIndex);
124
125                     // Start with the next series of input entries.
126
firstInputIndex = nextIndex;
127                 }
128             }
129         }
130     }
131
132
133     /**
134      * Transfers the specified input jars to the specified output jars.
135      */

136     private void writeOutput(ClassPool programClassPool,
137                              ClassPath classPath,
138                              int fromInputIndex,
139                              int fromOutputIndex,
140                              int toOutputIndex)
141     throws IOException JavaDoc
142     {
143         try
144         {
145             // Construct the writer that can write jars, wars, ears, zips, and
146
// directories, cascading over the specified output entries.
147
DataEntryWriter writer =
148                 DataEntryWriterFactory.createDataEntryWriter(classPath,
149                                                              fromOutputIndex,
150                                                              toOutputIndex);
151
152             // The writer will be used to write possibly obfuscated class files.
153
DataEntryReader classRewriter =
154                 new ClassRewriter(programClassPool, writer);
155
156             // The writer will also be used to write resource files.
157
DataEntryReader resourceRewriter =
158                 new DataEntryCopier(writer);
159
160             // Wrap the resource writer with a filter and a data entry renamer,
161
// if required.
162
if (configuration.adaptResourceFileNames != null)
163             {
164                 resourceRewriter =
165                     new FilteredDataEntryReader(
166                     new DataEntryNameFilter(new FileNameListMatcher(configuration.adaptResourceFileNames)),
167                     new DataEntryRenamer(programClassPool, resourceRewriter),
168                     resourceRewriter);
169             }
170
171             // Wrap the resource writer with a filter and a data entry rewriter,
172
// if required.
173
if (configuration.adaptResourceFileContents != null)
174             {
175                 resourceRewriter =
176                     new FilteredDataEntryReader(
177                     new DataEntryNameFilter(new FileNameListMatcher(configuration.adaptResourceFileContents)),
178                     new DataEntryRewriter(programClassPool, writer),
179                     resourceRewriter);
180             }
181
182             // Create the reader that can write class files and copy resource
183
// files to the above writer.
184
DataEntryReader reader =
185                 new ClassFilter(classRewriter, resourceRewriter);
186
187             // Go over the specified input entries and write their processed
188
// versions.
189
new InputReader(configuration).readInput(" Copying resources from program ",
190                                                      classPath,
191                                                      fromInputIndex,
192                                                      fromOutputIndex,
193                                                      reader);
194
195             // Close all output entries.
196
writer.close();
197         }
198         catch (IOException JavaDoc ex)
199         {
200             throw new IOException JavaDoc("Can't write [" + classPath.get(fromOutputIndex).getName() + "] (" + ex.getMessage() + ")");
201         }
202     }
203 }
204
Popular Tags