1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2013 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 */
21package proguard;
22
23import proguard.util.ListUtil;
24
25import java.io.*;
26import java.util.List;
27
28
29/**
30 * This class represents an entry from a class path: a jar, a war, a zip, an
31 * ear, or a directory, with a name and a flag to indicates whether the entry is
32 * an input entry or an output entry. Optional filters can be specified for the
33 * names of the contained resource/classes, jars, wars, ears, and zips.
34 *
35 * @author Eric Lafortune
36 */
37public class ClassPathEntry
38{
39    private File    file;
40    private boolean output;
41    private List    filter;
42    private List    jarFilter;
43    private List    warFilter;
44    private List    earFilter;
45    private List    zipFilter;
46
47
48    /**
49     * Creates a new ClassPathEntry with the given file and output flag.
50     */
51    public ClassPathEntry(File file, boolean isOutput)
52    {
53        this.file   = file;
54        this.output = isOutput;
55    }
56
57
58    /**
59     * Returns the path name of the entry.
60     */
61    public String getName()
62    {
63        try
64        {
65            return file.getCanonicalPath();
66        }
67        catch (IOException ex)
68        {
69            return file.getPath();
70        }
71    }
72
73
74    /**
75     * Returns the file.
76     */
77    public File getFile()
78    {
79        return file;
80    }
81
82
83    /**
84     * Sets the file.
85     */
86    public void setFile(File file)
87    {
88        this.file = file;
89    }
90
91
92    /**
93     * Returns whether this data entry is an output entry.
94     */
95    public boolean isOutput()
96    {
97        return output;
98    }
99
100
101    /**
102     * Specifies whether this data entry is an output entry.
103     */
104    public void setOutput(boolean output)
105    {
106        this.output = output;
107    }
108
109
110    /**
111     * Returns whether this data entry is a jar file.
112     */
113    public boolean isJar()
114    {
115        return hasExtension(".jar");
116    }
117
118
119    /**
120     * Returns whether this data entry is a war file.
121     */
122    public boolean isWar()
123    {
124        return hasExtension(".war");
125    }
126
127
128    /**
129     * Returns whether this data entry is a ear file.
130     */
131    public boolean isEar()
132    {
133        return hasExtension(".ear");
134    }
135
136
137    /**
138     * Returns whether this data entry is a zip file.
139     */
140    public boolean isZip()
141    {
142        return hasExtension(".zip");
143    }
144
145
146    /**
147     * Returns whether this data entry has the given extension.
148     */
149    private boolean hasExtension(String extension)
150    {
151        return endsWithIgnoreCase(file.getPath(), extension);
152    }
153
154
155    /**
156     * Returns whether the given string ends with the given suffix, ignoring
157     * its case.
158     */
159    private static boolean endsWithIgnoreCase(String string, String suffix)
160    {
161        int stringLength = string.length();
162        int suffixLength = suffix.length();
163
164        return string.regionMatches(true, stringLength -
165                                          suffixLength, suffix, 0, suffixLength);
166    }
167
168
169    /**
170     * Returns the name filter that is applied to bottom-level files in this entry.
171     */
172    public List getFilter()
173    {
174        return filter;
175    }
176
177    /**
178     * Sets the name filter that is applied to bottom-level files in this entry.
179     */
180    public void setFilter(List filter)
181    {
182        this.filter = filter == null || filter.size() == 0 ? null : filter;
183    }
184
185
186    /**
187     * Returns the name filter that is applied to jar files in this entry, if any.
188     */
189    public List getJarFilter()
190    {
191        return jarFilter;
192    }
193
194    /**
195     * Sets the name filter that is applied to jar files in this entry, if any.
196     */
197    public void setJarFilter(List filter)
198    {
199        this.jarFilter = filter == null || filter.size() == 0 ? null : filter;
200    }
201
202
203    /**
204     * Returns the name filter that is applied to war files in this entry, if any.
205     */
206    public List getWarFilter()
207    {
208        return warFilter;
209    }
210
211    /**
212     * Sets the name filter that is applied to war files in this entry, if any.
213     */
214    public void setWarFilter(List filter)
215    {
216        this.warFilter = filter == null || filter.size() == 0 ? null : filter;
217    }
218
219
220    /**
221     * Returns the name filter that is applied to ear files in this entry, if any.
222     */
223    public List getEarFilter()
224    {
225        return earFilter;
226    }
227
228    /**
229     * Sets the name filter that is applied to ear files in this entry, if any.
230     */
231    public void setEarFilter(List filter)
232    {
233        this.earFilter = filter == null || filter.size() == 0 ? null : filter;
234    }
235
236
237    /**
238     * Returns the name filter that is applied to zip files in this entry, if any.
239     */
240    public List getZipFilter()
241    {
242        return zipFilter;
243    }
244
245    /**
246     * Sets the name filter that is applied to zip files in this entry, if any.
247     */
248    public void setZipFilter(List filter)
249    {
250        this.zipFilter = filter == null || filter.size() == 0 ? null : filter;
251    }
252
253
254    // Implementations for Object.
255
256    public String toString()
257    {
258        String string = getName();
259
260        if (filter    != null ||
261            jarFilter != null ||
262            warFilter != null ||
263            earFilter != null ||
264            zipFilter != null)
265        {
266            string +=
267                ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD +
268                (zipFilter != null ? ListUtil.commaSeparatedString(zipFilter, true) : "")  +
269                ConfigurationConstants.SEPARATOR_KEYWORD +
270                (earFilter != null ? ListUtil.commaSeparatedString(earFilter, true) : "")  +
271                ConfigurationConstants.SEPARATOR_KEYWORD +
272                (warFilter != null ? ListUtil.commaSeparatedString(warFilter, true) : "")  +
273                ConfigurationConstants.SEPARATOR_KEYWORD +
274                (jarFilter != null ? ListUtil.commaSeparatedString(jarFilter, true) : "")  +
275                ConfigurationConstants.SEPARATOR_KEYWORD +
276                (filter    != null ? ListUtil.commaSeparatedString(filter, true)    : "")  +
277                ConfigurationConstants.CLOSE_ARGUMENTS_KEYWORD;
278        }
279
280        return string;
281    }
282}
283