/******************************************************************************* JarSizeTask - Ant task to update the MIDlet-Jar-Size property inside a JAR file Copyright (C) 2003 Manuel Linsmayer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *******************************************************************************/ import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.zip.CRC32; import java.util.zip.Deflater; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; public class JarSizeTask extends Task { // JAR file to update private File file; // Sets the file to update public void setFile(File file) { this.file = file; } // Task implementation public void execute() throws BuildException { // Check whether file exists if (!this.file.isFile()) { throw (new BuildException(file.toString() + " does not exist or is not a file")); } // Loop counter int i = 0; // False if Manifest should not be compressed boolean compressManifest = true; long lengthBefore; long lengthAfter; // Loop until MIDlet-Jar-Size property and real JAR filesize match do { // Update MIDlet-Jar-Size property lengthBefore = this.file.length(); this.update(compressManifest); lengthAfter = this.file.length(); // Increase loop counter and check loop number if (i++ > 2) { compressManifest = false; } } while (lengthBefore != lengthAfter); // Output success message System.out.println("MIDlet-Jar-Size property successfully updated"); } // Updates MIDlet-Jar-Size property inside the Manifest public void update(boolean compressManifest) throws BuildException { // Catch some exceptions try { // Open file to update FileInputStream fis = new FileInputStream(this.file); ZipInputStream zis = new ZipInputStream(fis); // Open temporary file File temp = File.createTempFile("jst", ".jar", this.file.getParentFile()); FileOutputStream fos = new FileOutputStream(temp); ZipOutputStream zos = new ZipOutputStream(fos); // Best compression zos.setLevel(Deflater.BEST_COMPRESSION); // Local variables ZipEntry ze, newZe; CRC32 checksum = new CRC32(); byte[] buf = new byte[1024]; // Loop until no more entry is available while ((ze = zis.getNextEntry()) != null) { // Check for Manifest entry if (ze.getName().equals("META-INF/MANIFEST.MF")) { // Read Manifest and update MIDlet-Jar-Size property BufferedReader br = new BufferedReader(new InputStreamReader(zis)); StringBuffer sb = new StringBuffer(); String line; while ((line = br.readLine()) != null) { if (line.indexOf("MIDlet-Jar-Size") == -1) { sb.append(line); } else { sb.append("MIDlet-Jar-Size: " + this.file.length()); } sb.append('\n'); } zis.closeEntry(); // Convert to raw bytes byte[] raw = sb.toString().getBytes(); // Create new ZipEntry, update checksum and other attributes newZe = new ZipEntry(ze); checksum.update(raw); ze.setCrc(checksum.getValue()); ze.setSize(raw.length); ze.setMethod(compressManifest ? Deflater.DEFLATED : Deflater.NO_COMPRESSION); ze.setCompressedSize(-1); // Don't know compressed size // Write entry zos.putNextEntry(ze); zos.write(raw, 0, raw.length); zos.closeEntry(); } // Other entry else { // Copy entry from original file to temporary file without changing anything newZe = new ZipEntry(ze); newZe.setCompressedSize(-1); // Don't know compressed size zos.putNextEntry(newZe); while (zis.available() != 0) { int len = zis.read(buf, 0, 1024); if (len != -1) { zos.write(buf, 0, len); } } zos.closeEntry(); zis.closeEntry(); } } // Close files zis.close(); zos.close(); // Delete original file, replace with temporary file if (!this.file.delete() || !temp.renameTo(this.file)) { throw (new BuildException("Could not delete or create " + file)); } } // Rewrite IOException to BuildException catch (IOException e) { throw (new BuildException(e.getMessage())); } } }