DataEntryReaderFactory.java revision b72c5c2e5482cf10117b2b25f642f7616b2326c3
1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2009 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.io.*;
24import proguard.util.*;
25
26import java.util.List;
27
28
29/**
30 * This class can create DataEntryReader instances based on class path entries.
31 * The readers will unwrap the input data entries from any jars, wars, ears,
32 * and zips, before passing them to a given reader.
33 *
34 * @author Eric Lafortune
35 */
36public class DataEntryReaderFactory
37{
38    /**
39     * Creates a DataEntryReader that can read the given class path entry.
40     *
41     * @param messagePrefix  a prefix for messages that are printed out.
42     * @param classPathEntry the input class path entry.
43     * @param reader         a data entry reader to which the reading of actual
44     *                       classes and resource files can be delegated.
45     * @return a DataEntryReader for reading the given class path entry.
46     */
47    public static DataEntryReader createDataEntryReader(String          messagePrefix,
48                                                        ClassPathEntry  classPathEntry,
49                                                        DataEntryReader reader)
50    {
51        String entryName = classPathEntry.getName();
52        boolean isJar = endsWithIgnoreCase(entryName, ".jar");
53        boolean isWar = endsWithIgnoreCase(entryName, ".war");
54        boolean isEar = endsWithIgnoreCase(entryName, ".ear");
55        boolean isZip = endsWithIgnoreCase(entryName, ".zip");
56
57        List filter    = classPathEntry.getFilter();
58        List jarFilter = classPathEntry.getJarFilter();
59        List warFilter = classPathEntry.getWarFilter();
60        List earFilter = classPathEntry.getEarFilter();
61        List zipFilter = classPathEntry.getZipFilter();
62
63        System.out.println(messagePrefix +
64                           (isJar ? "jar" :
65                            isWar ? "war" :
66                            isEar ? "ear" :
67                            isZip ? "zip" :
68                                    "directory") +
69                           " [" + classPathEntry.getName() + "]" +
70                           (filter    != null ||
71                            jarFilter != null ||
72                            warFilter != null ||
73                            earFilter != null ||
74                            zipFilter != null ? " (filtered)" : ""));
75
76        // Add a filter, if specified.
77        if (filter != null)
78        {
79            reader = new FilteredDataEntryReader(
80                     new DataEntryNameFilter(
81                     new ListParser(new FileNameParser()).parse(filter)),
82                         reader);
83        }
84
85        // Unzip any jars, if necessary.
86        reader = wrapInJarReader(reader, isJar, jarFilter, ".jar");
87        if (!isJar)
88        {
89            // Unzip any wars, if necessary.
90            reader = wrapInJarReader(reader, isWar, warFilter, ".war");
91            if (!isWar)
92            {
93                // Unzip any ears, if necessary.
94                reader = wrapInJarReader(reader, isEar, earFilter, ".ear");
95                if (!isEar)
96                {
97                    // Unzip any zips, if necessary.
98                    reader = wrapInJarReader(reader, isZip, zipFilter, ".zip");
99                }
100            }
101        }
102
103        return reader;
104    }
105
106
107    /**
108     *  Wraps the given DataEntryReader in a JarReader, filtering it if necessary.
109     */
110    private static DataEntryReader wrapInJarReader(DataEntryReader reader,
111                                                   boolean         isJar,
112                                                   List            jarFilter,
113                                                   String          jarExtension)
114    {
115        // Unzip any jars, if necessary.
116        DataEntryReader jarReader = new JarReader(reader);
117
118        if (isJar)
119        {
120            // Always unzip.
121            return jarReader;
122        }
123        else
124        {
125            // Add a filter, if specified.
126            if (jarFilter != null)
127            {
128                jarReader = new FilteredDataEntryReader(
129                            new DataEntryNameFilter(
130                            new ListParser(new FileNameParser()).parse(jarFilter)),
131                                jarReader);
132            }
133
134            // Only unzip the right type of jars.
135            return new FilteredDataEntryReader(
136                   new DataEntryNameFilter(
137                   new ExtensionMatcher(jarExtension)),
138                       jarReader,
139                       reader);
140        }
141    }
142
143
144    /**
145     * Returns whether the given string ends with the given suffix, ignoring its
146     * case.
147     */
148    private static boolean endsWithIgnoreCase(String string, String suffix)
149    {
150        int stringLength = string.length();
151        int suffixLength = suffix.length();
152
153        return string.regionMatches(true, stringLength - suffixLength, suffix, 0, suffixLength);
154    }
155}
156