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.io.*; 24import proguard.util.*; 25 26import java.util.List; 27 28/** 29 * This class can create DataEntryWriter instances based on class paths. The 30 * writers will wrap the output in the proper jars, wars, ears, and zips. 31 * 32 * @author Eric Lafortune 33 */ 34public class DataEntryWriterFactory 35{ 36 /** 37 * Creates a DataEntryWriter that can write to the given class path entries. 38 * 39 * @param classPath the output class path. 40 * @param fromIndex the start index in the class path. 41 * @param toIndex the end index in the class path. 42 * @return a DataEntryWriter for writing to the given class path entries. 43 */ 44 public static DataEntryWriter createDataEntryWriter(ClassPath classPath, 45 int fromIndex, 46 int toIndex) 47 { 48 DataEntryWriter writer = null; 49 50 // Create a chain of writers, one for each class path entry. 51 for (int index = toIndex - 1; index >= fromIndex; index--) 52 { 53 ClassPathEntry entry = classPath.get(index); 54 writer = createClassPathEntryWriter(entry, writer); 55 } 56 57 return writer; 58 } 59 60 61 /** 62 * Creates a DataEntryWriter that can write to the given class path entry, 63 * or delegate to another DataEntryWriter if its filters don't match. 64 */ 65 private static DataEntryWriter createClassPathEntryWriter(ClassPathEntry classPathEntry, 66 DataEntryWriter alternativeWriter) 67 { 68 boolean isJar = classPathEntry.isJar(); 69 boolean isWar = classPathEntry.isWar(); 70 boolean isEar = classPathEntry.isEar(); 71 boolean isZip = classPathEntry.isZip(); 72 73 List filter = classPathEntry.getFilter(); 74 List jarFilter = classPathEntry.getJarFilter(); 75 List warFilter = classPathEntry.getWarFilter(); 76 List earFilter = classPathEntry.getEarFilter(); 77 List zipFilter = classPathEntry.getZipFilter(); 78 79 System.out.println("Preparing output " + 80 (isJar ? "jar" : 81 isWar ? "war" : 82 isEar ? "ear" : 83 isZip ? "zip" : 84 "directory") + 85 " [" + classPathEntry.getName() + "]" + 86 (filter != null || 87 jarFilter != null || 88 warFilter != null || 89 earFilter != null || 90 zipFilter != null ? " (filtered)" : "")); 91 92 DataEntryWriter writer = new DirectoryWriter(classPathEntry.getFile(), 93 isJar || 94 isWar || 95 isEar || 96 isZip); 97 98 // Set up the filtered jar writers. 99 writer = wrapInJarWriter(writer, isZip, zipFilter, ".zip", isJar || isWar || isEar); 100 writer = wrapInJarWriter(writer, isEar, earFilter, ".ear", isJar || isWar); 101 writer = wrapInJarWriter(writer, isWar, warFilter, ".war", isJar); 102 writer = wrapInJarWriter(writer, isJar, jarFilter, ".jar", false); 103 104 // Add a filter, if specified. 105 writer = filter != null? 106 new FilteredDataEntryWriter( 107 new DataEntryNameFilter( 108 new ListParser(new FileNameParser()).parse(filter)), 109 writer) : 110 writer; 111 112 // Let the writer cascade, if specified. 113 return alternativeWriter != null ? 114 new CascadingDataEntryWriter(writer, alternativeWriter) : 115 writer; 116 } 117 118 119 /** 120 * Wraps the given DataEntryWriter in a JarWriter, filtering if necessary. 121 */ 122 private static DataEntryWriter wrapInJarWriter(DataEntryWriter writer, 123 boolean isJar, 124 List jarFilter, 125 String jarExtension, 126 boolean dontWrap) 127 { 128 // Zip up jars, if necessary. 129 DataEntryWriter jarWriter = dontWrap ? 130 (DataEntryWriter)new ParentDataEntryWriter(writer) : 131 (DataEntryWriter)new JarWriter(writer); 132 133 // Add a filter, if specified. 134 DataEntryWriter filteredJarWriter = jarFilter != null? 135 new FilteredDataEntryWriter( 136 new DataEntryParentFilter( 137 new DataEntryNameFilter( 138 new ListParser(new FileNameParser()).parse(jarFilter))), 139 jarWriter) : 140 jarWriter; 141 142 // Only zip up jars, unless the output is a jar file itself. 143 return new FilteredDataEntryWriter( 144 new DataEntryParentFilter( 145 new DataEntryNameFilter( 146 new ExtensionMatcher(jarExtension))), 147 filteredJarWriter, 148 isJar ? jarWriter : writer); 149 } 150} 151