1 /** 2 * Copyright 2008 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.tonicsystems.jarjar.util; 18 19 import java.io.*; 20 import java.util.ArrayList; 21 import java.util.Collections; 22 import java.util.Comparator; 23 import java.util.Enumeration; 24 import java.util.zip.ZipEntry; 25 import java.util.zip.ZipFile; 26 import java.util.zip.ZipOutputStream; 27 28 class IoUtil { 29 private IoUtil() {} 30 31 public static void pipe(InputStream is, OutputStream out, byte[] buf) throws IOException { 32 for (;;) { 33 int amt = is.read(buf); 34 if (amt < 0) 35 break; 36 out.write(buf, 0, amt); 37 } 38 } 39 40 public static void copy(File from, File to, byte[] buf) throws IOException { 41 InputStream in = new FileInputStream(from); 42 try { 43 OutputStream out = new FileOutputStream(to); 44 try { 45 pipe(in, out, buf); 46 } finally { 47 out.close(); 48 } 49 } finally { 50 in.close(); 51 } 52 } 53 54 /** 55 * Create a copy of an zip file without its empty directories. 56 * @param inputFile 57 * @param outputFile 58 * @throws IOException 59 */ 60 public static void copyZipWithoutEmptyDirectories(final File inputFile, final File outputFile) throws IOException 61 { 62 final byte[] buf = new byte[0x2000]; 63 64 final ZipFile inputZip = new ZipFile(inputFile); 65 final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(outputFile)); 66 try 67 { 68 // read a the entries of the input zip file and sort them 69 final Enumeration<? extends ZipEntry> e = inputZip.entries(); 70 final ArrayList<ZipEntry> sortedList = new ArrayList<ZipEntry>(); 71 while (e.hasMoreElements()) { 72 final ZipEntry entry = e.nextElement(); 73 sortedList.add(entry); 74 } 75 76 Collections.sort(sortedList, new Comparator<ZipEntry>() 77 { 78 public int compare(ZipEntry o1, ZipEntry o2) 79 { 80 return o1.getName().compareTo(o2.getName()); 81 } 82 }); 83 84 // treat them again and write them in output, wenn they not are empty directories 85 for (int i = sortedList.size()-1; i>=0; i--) 86 { 87 final ZipEntry inputEntry = sortedList.get(i); 88 final String name = inputEntry.getName(); 89 final boolean isEmptyDirectory; 90 if (inputEntry.isDirectory()) 91 { 92 if (i == sortedList.size()-1) 93 { 94 // no item afterwards; it was an empty directory 95 isEmptyDirectory = true; 96 } 97 else 98 { 99 final String nextName = sortedList.get(i+1).getName(); 100 isEmptyDirectory = !nextName.startsWith(name); 101 } 102 } 103 else 104 { 105 isEmptyDirectory = false; 106 } 107 108 109 // write the entry 110 if (isEmptyDirectory) 111 { 112 sortedList.remove(inputEntry); 113 } 114 else 115 { 116 final ZipEntry outputEntry = new ZipEntry(inputEntry); 117 outputStream.putNextEntry(outputEntry); 118 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 119 final InputStream is = inputZip.getInputStream(inputEntry); 120 IoUtil.pipe(is, baos, buf); 121 is.close(); 122 outputStream.write(baos.toByteArray()); 123 } 124 } 125 } finally { 126 outputStream.close(); 127 } 128 129 } 130 131 } 132